@stacksjs/ts-cloud 0.2.26 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aws/ec2.d.ts +23 -0
- package/dist/aws/lambda.d.ts +7 -0
- package/dist/bin/cli.js +588 -571
- package/dist/deploy/site-target.d.ts +7 -1
- package/dist/drivers/aws/driver.d.ts +21 -0
- package/dist/drivers/aws/provision.d.ts +41 -0
- package/dist/drivers/hetzner/client.d.ts +46 -0
- package/dist/drivers/hetzner/cloud-init.d.ts +7 -18
- package/dist/drivers/hetzner/driver.d.ts +24 -0
- package/dist/drivers/hetzner/state.d.ts +8 -2
- package/dist/drivers/shared/backups.d.ts +28 -0
- package/dist/drivers/shared/certbot.d.ts +38 -0
- package/dist/drivers/shared/compute-deploy.d.ts +1 -1
- package/dist/drivers/shared/compute-provision.d.ts +29 -0
- package/dist/drivers/shared/db-provision.d.ts +30 -0
- package/dist/drivers/shared/deploy-script.d.ts +0 -3
- package/dist/drivers/shared/env-file.d.ts +12 -0
- package/dist/drivers/shared/fleet.d.ts +34 -0
- package/dist/drivers/shared/git-deploy.d.ts +36 -0
- package/dist/drivers/shared/image-recipe.d.ts +40 -0
- package/dist/drivers/shared/laravel-deploy.d.ts +42 -0
- package/dist/drivers/shared/laravel-services.d.ts +36 -0
- package/dist/drivers/shared/maintenance.d.ts +10 -0
- package/dist/drivers/shared/monitoring.d.ts +15 -0
- package/dist/drivers/shared/nginx-vhost.d.ts +76 -0
- package/dist/drivers/shared/notifications.d.ts +40 -0
- package/dist/drivers/shared/php-provision.d.ts +38 -0
- package/dist/drivers/shared/releases.d.ts +52 -0
- package/dist/drivers/shared/ssh-keys.d.ts +21 -0
- package/dist/drivers/shared/ubuntu-bootstrap.d.ts +54 -0
- package/dist/drivers/shared/ufw.d.ts +17 -0
- package/dist/index.js +58606 -56962
- package/dist/security/pre-deploy-scanner.d.ts +12 -0
- package/package.json +3 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate an nginx server block (vhost) for a Forge-style site and the shell
|
|
3
|
+
* commands that install it.
|
|
4
|
+
*
|
|
5
|
+
* Site `type` drives the template:
|
|
6
|
+
* - `laravel` / `statamic` / `wordpress` — `public/` web root, `index.php`,
|
|
7
|
+
* `try_files … /index.php?$query_string`, and a `fastcgi_pass` to the site's
|
|
8
|
+
* php-fpm socket (see {@link import('./php-provision').phpFpmSocketPath}).
|
|
9
|
+
* - `php` — generic PHP app behind php-fpm, web root at the release root.
|
|
10
|
+
* - `static` — plain files, `try_files … =404`.
|
|
11
|
+
* - `spa` — SPA fallback to `/index.html`.
|
|
12
|
+
*
|
|
13
|
+
* The block listens on :80 only; TLS (the `:443` block + redirect) is layered
|
|
14
|
+
* on by certbot in the SSL step, so this stays stable across cert renewals.
|
|
15
|
+
*/
|
|
16
|
+
import type { SiteConfig } from '@ts-cloud/core';
|
|
17
|
+
export type NginxSiteType = NonNullable<SiteConfig['type']>;
|
|
18
|
+
export interface NginxVhostOptions {
|
|
19
|
+
/** Site key — names the config file (`/etc/nginx/sites-available/<siteName>`). */
|
|
20
|
+
siteName: string;
|
|
21
|
+
/** Primary hostname (`server_name`). */
|
|
22
|
+
domain: string;
|
|
23
|
+
/** Additional hostnames added to `server_name`. */
|
|
24
|
+
aliases?: string[];
|
|
25
|
+
/** Site type — selects the template. @default 'laravel' */
|
|
26
|
+
type?: NginxSiteType;
|
|
27
|
+
/**
|
|
28
|
+
* Directory the vhost serves from. For zero-downtime sites this is the
|
|
29
|
+
* `current` symlink (`/var/www/<site>/current`); the web root appends
|
|
30
|
+
* {@link webDirectory}.
|
|
31
|
+
*/
|
|
32
|
+
appDir: string;
|
|
33
|
+
/** Web root relative to {@link appDir}. Defaults per type (see {@link defaultWebDirectory}). */
|
|
34
|
+
webDirectory?: string;
|
|
35
|
+
/** PHP version selecting the php-fpm socket. @default '8.3' */
|
|
36
|
+
phpVersion?: string;
|
|
37
|
+
/** `from path` → `to URL` 301 redirects. */
|
|
38
|
+
redirects?: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Serve TLS directly from this vhost using operator-provided certs. When set,
|
|
41
|
+
* the :80 block becomes an HTTPS redirect and a :443 `ssl` block serves the
|
|
42
|
+
* site. Used for the `custom` SSL provider; for Let's Encrypt, certbot
|
|
43
|
+
* rewrites the :80 block itself (leave this unset).
|
|
44
|
+
*/
|
|
45
|
+
ssl?: {
|
|
46
|
+
certPath: string;
|
|
47
|
+
keyPath: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* HTTP Basic auth (htpasswd). When set, the vhost requires auth and the
|
|
51
|
+
* generated script writes the htpasswd file. The `realm` is shown in the
|
|
52
|
+
* browser prompt.
|
|
53
|
+
*/
|
|
54
|
+
auth?: {
|
|
55
|
+
username: string;
|
|
56
|
+
password: string;
|
|
57
|
+
realm?: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Path of the htpasswd file for a site. */
|
|
61
|
+
export declare function htpasswdPath(siteName: string): string;
|
|
62
|
+
/** Whether a site type is served by php-fpm. */
|
|
63
|
+
export declare function isPhpSiteType(type: NginxSiteType): boolean;
|
|
64
|
+
/** Default web root (relative to the release dir) for a site type. */
|
|
65
|
+
export declare function defaultWebDirectory(type: NginxSiteType): string;
|
|
66
|
+
/**
|
|
67
|
+
* Build the nginx server block text for a site. With `options.ssl`, emits a
|
|
68
|
+
* :80 → HTTPS redirect plus a :443 `ssl` block (the `custom` cert path);
|
|
69
|
+
* otherwise a single :80 block (certbot upgrades it for Let's Encrypt).
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildNginxVhost(options: NginxVhostOptions): string;
|
|
72
|
+
/**
|
|
73
|
+
* Build the shell commands that write the vhost, enable it, validate the nginx
|
|
74
|
+
* config, and reload. Re-runnable (overwrites the config + refreshes the symlink).
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildNginxVhostScript(options: NginxVhostOptions): string[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send deploy / SSL / health-check / backup notifications to the configured
|
|
3
|
+
* channels (Slack, Discord, Telegram, email, generic webhook), mirroring
|
|
4
|
+
* Forge's notification system.
|
|
5
|
+
*
|
|
6
|
+
* Two surfaces:
|
|
7
|
+
* - {@link sendNotifications} — called from the TS deploy orchestrator for
|
|
8
|
+
* deploy success/failure (and other events ts-cloud drives locally).
|
|
9
|
+
* - {@link buildNotifierScript} — generates an on-box `ts-cloud-notify`
|
|
10
|
+
* helper that cron-driven events (certbot renewal, backups) can call.
|
|
11
|
+
*/
|
|
12
|
+
import type { NotifyEvent, NotificationsConfig } from '@ts-cloud/core';
|
|
13
|
+
/** Fetch implementation (injectable for tests). */
|
|
14
|
+
export type FetchLike = (input: string, init?: {
|
|
15
|
+
method?: string;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
body?: string;
|
|
18
|
+
}) => Promise<{
|
|
19
|
+
ok: boolean;
|
|
20
|
+
status: number;
|
|
21
|
+
}>;
|
|
22
|
+
export interface SendNotificationsOptions {
|
|
23
|
+
/** Override the fetch implementation (default: global `fetch`). */
|
|
24
|
+
fetchImpl?: FetchLike;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Send `message` for `event` to every configured + subscribed channel. Errors
|
|
28
|
+
* on individual channels are swallowed (a flaky webhook must not fail a deploy);
|
|
29
|
+
* returns the list of channels that were attempted.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sendNotifications(config: NotificationsConfig | undefined, event: NotifyEvent, message: string, options?: SendNotificationsOptions): Promise<string[]>;
|
|
32
|
+
/** Resolve the effective notifications config for a site (site overrides project). */
|
|
33
|
+
export declare function resolveNotifications(project: NotificationsConfig | undefined, site: NotificationsConfig | undefined): NotificationsConfig | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Generate an on-box `ts-cloud-notify` script that POSTs `$1` (a message) to
|
|
36
|
+
* the webhook channels. Used by cron-driven hooks (certbot renew, backups) so
|
|
37
|
+
* server-side events also reach Slack/Discord/etc. Returns `[]` when no
|
|
38
|
+
* webhook-style channel is configured.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildNotifierScript(config: NotificationsConfig | undefined): string[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the apt provisioning script for a Forge-style PHP box: nginx,
|
|
3
|
+
* one or more PHP-FPM versions (via `ppa:ondrej/php`), the standard Laravel
|
|
4
|
+
* extension set, and Composer.
|
|
5
|
+
*
|
|
6
|
+
* Returns an array of shell command lines (matching the convention of
|
|
7
|
+
* {@link import('./rpx-gateway').buildRpxProvisionScript}) so it can be spliced
|
|
8
|
+
* into the Ubuntu cloud-init bootstrap. Each requested PHP version installs its
|
|
9
|
+
* own `phpX.Y-fpm` pool so different sites can pin different versions and nginx
|
|
10
|
+
* can `fastcgi_pass` to the matching unix socket
|
|
11
|
+
* (`/run/php/phpX.Y-fpm.sock`).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Baseline PHP extension package suffixes installed for every version
|
|
15
|
+
* (`phpX.Y-<suffix>`). Covers Laravel's documented requirements plus the
|
|
16
|
+
* common drivers (mysql/pgsql/sqlite/redis) and image/locale/number stack.
|
|
17
|
+
*/
|
|
18
|
+
export declare const LARAVEL_PHP_EXTENSIONS: readonly string[];
|
|
19
|
+
export interface PhpProvisionOptions {
|
|
20
|
+
/** PHP versions to install (e.g. `['8.3', '8.2']`). @default ['8.3'] */
|
|
21
|
+
versions?: string[];
|
|
22
|
+
/** Default PHP version (sets the `php` CLI alternative). @default first of `versions` */
|
|
23
|
+
default?: string;
|
|
24
|
+
/** Extra extension suffixes beyond {@link LARAVEL_PHP_EXTENSIONS} (e.g. `['imagick']`). */
|
|
25
|
+
extensions?: string[];
|
|
26
|
+
/** Install + enable nginx. @default true */
|
|
27
|
+
installNginx?: boolean;
|
|
28
|
+
/** Install Composer to `/usr/local/bin/composer`. @default true */
|
|
29
|
+
installComposer?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Per-version apt package names for the given extension suffixes. */
|
|
32
|
+
export declare function phpPackagesForVersion(version: string, extensions: readonly string[]): string[];
|
|
33
|
+
/** Absolute php-fpm unix socket path for a version (matches ondrej's layout). */
|
|
34
|
+
export declare function phpFpmSocketPath(version: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Build the shell command lines that provision PHP-FPM, nginx, and Composer.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildPhpProvisionScript(options?: PhpProvisionOptions): string[];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-downtime atomic release management for Forge-style git deploys.
|
|
3
|
+
*
|
|
4
|
+
* Directory layout under a site's base (`/var/www/<site>`):
|
|
5
|
+
* releases/<id>/ one checkout per deploy
|
|
6
|
+
* shared/ files persisted across releases (storage, .env, …)
|
|
7
|
+
* current -> symlink to the active release
|
|
8
|
+
*
|
|
9
|
+
* A deploy clones into `releases/<id>`, symlinks the shared paths in, runs the
|
|
10
|
+
* deploy script, then atomically repoints `current`. Old releases are pruned
|
|
11
|
+
* to a retention count for rollback. These map to Forge's deploy macros:
|
|
12
|
+
* $CREATE_RELEASE → {@link buildEnsureReleaseLayout} + git clone + {@link buildLinkSharedPaths}
|
|
13
|
+
* $ACTIVATE_RELEASE → {@link buildActivateRelease} (+ {@link buildPruneReleases})
|
|
14
|
+
*/
|
|
15
|
+
/** Paths that are always shared across releases (Forge shares `.env` implicitly). */
|
|
16
|
+
export declare const DEFAULT_SHARED_PATHS: readonly string[];
|
|
17
|
+
/** Default number of past releases to retain for rollback. */
|
|
18
|
+
export declare const DEFAULT_KEEP_RELEASES = 4;
|
|
19
|
+
export interface ReleasePaths {
|
|
20
|
+
/** Site base directory (`/var/www/<site>`). */
|
|
21
|
+
base: string;
|
|
22
|
+
/** Releases parent (`<base>/releases`). */
|
|
23
|
+
releases: string;
|
|
24
|
+
/** Shared parent (`<base>/shared`). */
|
|
25
|
+
shared: string;
|
|
26
|
+
/** Active-release symlink (`<base>/current`). */
|
|
27
|
+
current: string;
|
|
28
|
+
/** This deploy's release dir (`<base>/releases/<id>`). */
|
|
29
|
+
release: string;
|
|
30
|
+
}
|
|
31
|
+
/** Resolve the standard release layout paths for a site + release id. */
|
|
32
|
+
export declare function releasePaths(base: string, releaseId: string): ReleasePaths;
|
|
33
|
+
/**
|
|
34
|
+
* Ensure the releases/ and shared/ skeleton exist, including the Laravel
|
|
35
|
+
* `storage` tree and an empty shared `.env` so symlinks never dangle.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildEnsureReleaseLayout(paths: ReleasePaths, sharedPaths?: readonly string[]): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Symlink every shared path from `shared/` into the freshly checked-out release,
|
|
40
|
+
* replacing whatever the checkout shipped (e.g. the repo's empty `storage`).
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildLinkSharedPaths(paths: ReleasePaths, sharedPaths?: readonly string[]): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Atomically repoint `current` at the new release. Writes a temp symlink and
|
|
45
|
+
* `mv -T`s it over `current` so there is no window where `current` is missing.
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildActivateRelease(paths: ReleasePaths): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Remove all but the newest `keep` releases (by mtime). `current` always points
|
|
50
|
+
* at the newest, so it is never pruned.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildPruneReleases(paths: ReleasePaths, keep?: number): string[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declaratively manage operator SSH keys in the box's `authorized_keys`.
|
|
3
|
+
*
|
|
4
|
+
* Keys are written inside a ts-cloud-managed block (delimited by marker
|
|
5
|
+
* comments) so the set can be reconciled on every provision/deploy without
|
|
6
|
+
* disturbing keys added out-of-band: the whole block is rewritten from the
|
|
7
|
+
* config each time. Adding an SSH key is therefore "add an entry + redeploy".
|
|
8
|
+
*/
|
|
9
|
+
import type { SshKeyConfig } from '@ts-cloud/core';
|
|
10
|
+
/** Default authorized_keys path (root deploy user). */
|
|
11
|
+
export declare const DEFAULT_AUTHORIZED_KEYS = "/root/.ssh/authorized_keys";
|
|
12
|
+
export interface AuthorizedKeysOptions {
|
|
13
|
+
/** authorized_keys file to manage. @default '/root/.ssh/authorized_keys' */
|
|
14
|
+
path?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build the commands that reconcile the managed key block in authorized_keys.
|
|
18
|
+
* Strips any previous ts-cloud block, then appends the current set. Returns `[]`
|
|
19
|
+
* when there are no keys to manage.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildAuthorizedKeysScript(keys?: SshKeyConfig[], options?: AuthorizedKeysOptions): string[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The canonical Ubuntu provisioning recipe for a ts-cloud compute box.
|
|
3
|
+
*
|
|
4
|
+
* This single bash builder is used in three places so there is exactly one
|
|
5
|
+
* source of truth (and zero per-provider divergence):
|
|
6
|
+
* - **cold boot** — Hetzner cloud-init / AWS EC2 UserData run it on first boot.
|
|
7
|
+
* - **image bake** — the golden-image pipeline runs it to pre-install the
|
|
8
|
+
* stack, then snapshots the box into a Hetzner snapshot / AWS AMI.
|
|
9
|
+
* - **baked boot** — when a box boots from a pre-provisioned image, pass
|
|
10
|
+
* `baked: true` to skip the install-heavy steps (apt/runtime/php/services)
|
|
11
|
+
* that are already in the image, keeping only cheap per-boot setup.
|
|
12
|
+
*
|
|
13
|
+
* Targets Ubuntu (apt) — Forge's platform — on every provider, so the apt
|
|
14
|
+
* provisioning, nginx vhosts, php-fpm sockets, and deploy scripts are identical
|
|
15
|
+
* for Hetzner and AWS.
|
|
16
|
+
*/
|
|
17
|
+
export interface UbuntuBootstrapOptions {
|
|
18
|
+
runtime?: 'bun' | 'node' | 'deno' | 'php';
|
|
19
|
+
runtimeVersion?: string;
|
|
20
|
+
systemPackages?: string[];
|
|
21
|
+
database?: 'sqlite' | 'mysql' | 'postgres';
|
|
22
|
+
/**
|
|
23
|
+
* Shell commands that install PHP-FPM + nginx + Composer, built by
|
|
24
|
+
* {@link import('./php-provision').buildPhpProvisionScript}. Spliced
|
|
25
|
+
* after the base packages so Laravel/PHP sites have their runtime ready
|
|
26
|
+
* before any deploy. Used when `runtime === 'php'` (or `compute.php` is set).
|
|
27
|
+
*/
|
|
28
|
+
phpProvision?: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Shell commands that install on-box services (database engine, redis,
|
|
31
|
+
* memcached, meilisearch) and create the app database + user, built by
|
|
32
|
+
* {@link import('./db-provision')}. Spliced after the PHP provision.
|
|
33
|
+
*/
|
|
34
|
+
servicesProvision?: string[];
|
|
35
|
+
caddyfile?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Shell commands that install + start the rpx reverse-proxy gateway, built by
|
|
38
|
+
* {@link import('./rpx-gateway').buildRpxProvisionScript}. Appended
|
|
39
|
+
* after the runtime is installed so `bun add -g @stacksjs/rpx` works. Mutually
|
|
40
|
+
* exclusive with `caddyfile` (the box runs one gateway).
|
|
41
|
+
*/
|
|
42
|
+
rpxProvision?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* The box boots from a pre-provisioned (golden) image that already has the
|
|
45
|
+
* runtime + PHP + services + base packages installed. Skip those install
|
|
46
|
+
* steps — only do the cheap per-boot setup (dirs, gateway config). Makes
|
|
47
|
+
* boot near-instant. @default false
|
|
48
|
+
*/
|
|
49
|
+
baked?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the Ubuntu provisioning bash script (with `#!/bin/bash` shebang).
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildUbuntuBootstrapScript(options?: UbuntuBootstrapOptions): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host firewall (UFW) provisioning, mirroring Forge's per-server firewall.
|
|
3
|
+
*
|
|
4
|
+
* Defaults to deny-incoming / allow-outgoing, with SSH (OpenSSH), HTTP (80),
|
|
5
|
+
* and HTTPS (443) always open so deploys and web traffic keep working, plus
|
|
6
|
+
* any extra ports the config lists (e.g. a Reverb/websocket port). On Hetzner
|
|
7
|
+
* this is layered on top of the cloud firewall; on a bare box it's the primary
|
|
8
|
+
* line of defence.
|
|
9
|
+
*/
|
|
10
|
+
import type { ComputeFirewallConfig } from '@ts-cloud/core';
|
|
11
|
+
/** Ports always allowed so SSH deploys + web traffic are never locked out. */
|
|
12
|
+
export declare const UFW_BASE_PORTS: readonly number[];
|
|
13
|
+
/**
|
|
14
|
+
* Build the UFW provisioning commands. Idempotent: `ufw allow` is a no-op when
|
|
15
|
+
* a rule already exists, and `--force enable` is safe to re-run.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildUfwScript(firewall?: ComputeFirewallConfig): string[];
|