@stacksjs/ts-cloud 0.2.26 → 0.3.0
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 +17 -2
- package/dist/bin/cli.js +1012 -914
- package/dist/deploy/serverless-app.d.ts +53 -0
- package/dist/deploy/serverless-app.test.d.ts +1 -0
- package/dist/deploy/serverless-image.d.ts +32 -0
- 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 +34 -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 +88 -0
- package/dist/drivers/shared/notifications.d.ts +40 -0
- package/dist/drivers/shared/package-manager.d.ts +84 -0
- package/dist/drivers/shared/php-provision.d.ts +36 -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 +38356 -35292
- package/dist/security/pre-deploy-scanner.d.ts +12 -0
- package/package.json +3 -3
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble the remote deploy script for a Forge-style PHP/Laravel site: a
|
|
3
|
+
* git-clone-on-server, zero-downtime atomic-release deploy.
|
|
4
|
+
*
|
|
5
|
+
* The deploy script is a list of steps run in order on the box. Three Forge
|
|
6
|
+
* macros expand to the release machinery:
|
|
7
|
+
* $CREATE_RELEASE — clone the repo into a new release dir, link shared
|
|
8
|
+
* paths, and `cd` into it (subsequent steps run there).
|
|
9
|
+
* $ACTIVATE_RELEASE — flip the `current` symlink atomically, prune old
|
|
10
|
+
* releases, and reload php-fpm so opcache sees new code.
|
|
11
|
+
* $RESTART_QUEUES — gracefully restart Laravel queue workers / Horizon.
|
|
12
|
+
*
|
|
13
|
+
* Everything between $CREATE_RELEASE and $ACTIVATE_RELEASE runs inside the new
|
|
14
|
+
* (not-yet-live) release, so a failure leaves the previous release serving —
|
|
15
|
+
* the Envoyer zero-downtime guarantee.
|
|
16
|
+
*/
|
|
17
|
+
import type { SiteConfig } from '@ts-cloud/core';
|
|
18
|
+
export declare const MACRO_CREATE_RELEASE = "$CREATE_RELEASE";
|
|
19
|
+
export declare const MACRO_ACTIVATE_RELEASE = "$ACTIVATE_RELEASE";
|
|
20
|
+
export declare const MACRO_RESTART_QUEUES = "$RESTART_QUEUES";
|
|
21
|
+
/**
|
|
22
|
+
* Default deploy script (with macros) for a site type. Overridden by
|
|
23
|
+
* {@link SiteConfig.deployScript}.
|
|
24
|
+
*/
|
|
25
|
+
export declare function defaultDeployScriptFor(type: NonNullable<SiteConfig['type']>): string[];
|
|
26
|
+
export interface LaravelDeployOptions {
|
|
27
|
+
siteName: string;
|
|
28
|
+
site: SiteConfig;
|
|
29
|
+
/** Unique release identifier (timestamp or sha) → `releases/<id>`. */
|
|
30
|
+
releaseId: string;
|
|
31
|
+
/** Site base dir. @default `/var/www/<siteName>` */
|
|
32
|
+
appBase?: string;
|
|
33
|
+
/** Exact commit to deploy (else the branch tip). */
|
|
34
|
+
commit?: string;
|
|
35
|
+
/** PHP version selecting the `phpX.Y` binary. @default `site.phpVersion` ?? '8.3' */
|
|
36
|
+
defaultPhpVersion?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the full remote shell script for a PHP/Laravel git deploy, expanding the
|
|
40
|
+
* release macros. Requires `site.repository` to be set.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildLaravelDeployScript(options: LaravelDeployOptions): string[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the per-site runtime services for a Forge-style PHP box: queue
|
|
3
|
+
* workers / Horizon (systemd), the Laravel scheduler (cron), and arbitrary
|
|
4
|
+
* daemons (systemd). Reconciled on every deploy so units track the config —
|
|
5
|
+
* units no longer in the config are stopped and removed.
|
|
6
|
+
*
|
|
7
|
+
* Unit naming (so a site's units can be globbed for pruning):
|
|
8
|
+
* <slug>-<site>-queue-<i>.service
|
|
9
|
+
* <slug>-<site>-daemon-<slug-of-name>.service
|
|
10
|
+
* Scheduler cron lives at /etc/cron.d/<slug>-<site>-scheduler.
|
|
11
|
+
*
|
|
12
|
+
* ExecStart commands target `<base>/current/...` (the active-release symlink),
|
|
13
|
+
* so workers/daemons always run the live code; `queue:restart` (run by the
|
|
14
|
+
* deploy's $RESTART_QUEUES macro) cycles them onto the new release.
|
|
15
|
+
*/
|
|
16
|
+
import type { DaemonConfig, SiteConfig } from '@ts-cloud/core';
|
|
17
|
+
export interface SiteServicesOptions {
|
|
18
|
+
slug: string;
|
|
19
|
+
siteName: string;
|
|
20
|
+
site: SiteConfig;
|
|
21
|
+
/** PHP version selecting the `phpX.Y` binary. @default '8.3' */
|
|
22
|
+
phpVersion?: string;
|
|
23
|
+
/** Site base dir. @default `/var/www/<siteName>` */
|
|
24
|
+
appBase?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function queueUnitName(slug: string, siteName: string, index: number): string;
|
|
27
|
+
export declare function daemonUnitName(slug: string, siteName: string, daemon: DaemonConfig, index: number): string;
|
|
28
|
+
/** Path of the scheduler cron file for a site. */
|
|
29
|
+
export declare function schedulerCronPath(slug: string, siteName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Build the full reconcile script: (re)write desired queue/daemon units +
|
|
32
|
+
* scheduler cron, prune stale units for this site, and reload systemd.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildSiteServicesScript(options: SiteServicesOptions): string[];
|
|
35
|
+
/** Whether a site declares any runtime services (avoids emitting an empty reconcile). */
|
|
36
|
+
export declare function siteHasServices(site: SiteConfig): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic unattended security/system updates, mirroring Forge's scheduled
|
|
3
|
+
* maintenance. Installs `unattended-upgrades` and enables the daily APT
|
|
4
|
+
* auto-update timers so security patches land without manual intervention.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build the commands that enable automatic security updates. Idempotent.
|
|
8
|
+
* Returns `[]` when disabled.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildAutoUpdatesScript(enabled?: boolean): string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight server monitoring, mirroring Forge's basic server metrics.
|
|
3
|
+
*
|
|
4
|
+
* Dependency-free: a small shell collector reads load average, memory, and
|
|
5
|
+
* disk usage and writes a JSON snapshot to `/var/lib/ts-cloud/metrics.json`
|
|
6
|
+
* every minute via a systemd timer. The ts-cloud UI (and any operator tooling)
|
|
7
|
+
* can read that file for at-a-glance server health.
|
|
8
|
+
*/
|
|
9
|
+
/** Where the metrics snapshot is written. */
|
|
10
|
+
export declare const METRICS_PATH = "/var/lib/ts-cloud/metrics.json";
|
|
11
|
+
/**
|
|
12
|
+
* Build the commands that install the metrics collector + systemd timer.
|
|
13
|
+
* Idempotent. Returns `[]` when disabled.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildMonitoringScript(enabled?: boolean): string[];
|
|
@@ -0,0 +1,88 @@
|
|
|
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[];
|
|
77
|
+
/** Wrapper that runs the pantry-installed nginx binary inside pantry's env. */
|
|
78
|
+
export declare const NGINX_WRAPPER = "/usr/local/bin/ts-cloud-nginx";
|
|
79
|
+
/**
|
|
80
|
+
* Set up ts-cloud-managed nginx on top of the pantry-installed nginx binary:
|
|
81
|
+
* a wrapper that runs nginx within `pantry env` (so it + its shared libs
|
|
82
|
+
* resolve), a full `/etc/nginx/nginx.conf` that `include`s the per-site vhosts,
|
|
83
|
+
* and a systemd unit on :80/:443. Replaces apt's nginx service (pantry's own
|
|
84
|
+
* nginx service serves a minimal :8080 default and isn't started here).
|
|
85
|
+
*
|
|
86
|
+
* Run once at provision time, after the nginx binary is installed.
|
|
87
|
+
*/
|
|
88
|
+
export declare function buildNginxServiceScript(projectDir?: string): 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,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pantry-based package manager for provisioned servers.
|
|
3
|
+
*
|
|
4
|
+
* Every server dependency ts-cloud installs — PHP, nginx, Composer, the
|
|
5
|
+
* databases/caches/search engines, and the language runtimes — comes from the
|
|
6
|
+
* pantry registry (`registry.pantry.dev`, Hetzner-backed object storage) via
|
|
7
|
+
* the `pantry` CLI instead of apt/ppa/curl installers. Long-running services
|
|
8
|
+
* are managed by pantry's own systemd integration, which runs in **system
|
|
9
|
+
* scope** when provisioning as root (units under `/etc/systemd/system`, started
|
|
10
|
+
* at boot) — see `PANTRY_SERVICE_SCOPE` in pantry's service controller.
|
|
11
|
+
*
|
|
12
|
+
* This module is the single chokepoint for "install package X" / "run service
|
|
13
|
+
* Y" so the Hetzner and AWS bootstrap paths share one implementation. It only
|
|
14
|
+
* emits shell command lines (the convention used across `drivers/shared`); the
|
|
15
|
+
* caller splices them into the Ubuntu cloud-init / SSM bootstrap.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Pantry package domains for the dependencies ts-cloud provisions. Domains
|
|
19
|
+
* (not aliases) are used because aliases aren't guaranteed in every released
|
|
20
|
+
* pantry binary. The recipes live in pantry's `src/packages/*` (e.g. `php.net`
|
|
21
|
+
* is a source build carrying the full Laravel extension matrix).
|
|
22
|
+
*/
|
|
23
|
+
export declare const PANTRY_PACKAGES: {
|
|
24
|
+
readonly php: "php.net";
|
|
25
|
+
readonly nginx: "nginx.org";
|
|
26
|
+
readonly composer: "getcomposer.org";
|
|
27
|
+
readonly mysql: "mysql.com";
|
|
28
|
+
readonly mariadb: "mariadb.org";
|
|
29
|
+
readonly postgres: "postgresql.org";
|
|
30
|
+
readonly redis: "redis.io";
|
|
31
|
+
readonly memcached: "memcached.org";
|
|
32
|
+
readonly meilisearch: "meilisearch.com";
|
|
33
|
+
readonly git: "git-scm.com";
|
|
34
|
+
readonly certbot: "certbot.eff.org";
|
|
35
|
+
readonly bun: "bun.sh";
|
|
36
|
+
readonly node: "nodejs.org";
|
|
37
|
+
readonly deno: "deno.land";
|
|
38
|
+
};
|
|
39
|
+
/** Logical package key (`'php'`, `'nginx'`, …). */
|
|
40
|
+
export type PantryPackageKey = keyof typeof PANTRY_PACKAGES;
|
|
41
|
+
/** A fully-qualified pantry package domain (`'php.net'`, `'nginx.org'`, …). */
|
|
42
|
+
export type PantryPackageDomain = (typeof PANTRY_PACKAGES)[PantryPackageKey];
|
|
43
|
+
/** A package to install: a known domain, optionally pinned with `@<version>`. */
|
|
44
|
+
export type PantrySpec = PantryPackageDomain | `${PantryPackageDomain}@${string}`;
|
|
45
|
+
/** Where the `pantry` binary itself is installed (on PATH for all later steps). */
|
|
46
|
+
export declare const PANTRY_INSTALL_DIR = "/usr/local/bin";
|
|
47
|
+
/**
|
|
48
|
+
* Server-side pantry project root. `pantry install` is project-scoped — it
|
|
49
|
+
* writes packages under `<root>/pantry/` and exposes their binaries via
|
|
50
|
+
* `<root>/pantry/.bin`. Provisioning installs everything into this one fixed
|
|
51
|
+
* project so the env (and thus PATH) is stable across deploy/systemd steps.
|
|
52
|
+
*/
|
|
53
|
+
export declare const PANTRY_PROJECT_DIR = "/opt/pantry";
|
|
54
|
+
export interface PantryBootstrapOptions {
|
|
55
|
+
/** Pin the pantry CLI version (e.g. `'0.9.39'`). @default latest release */
|
|
56
|
+
version?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Bootstrap the `pantry` CLI on a fresh server (idempotent — skips when already
|
|
60
|
+
* present). Installs to {@link PANTRY_INSTALL_DIR} and selects system-scope
|
|
61
|
+
* service management so `pantry enable/start` provisions boot-time systemd
|
|
62
|
+
* units rather than the per-user units that can't run headlessly.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildPantryBootstrapScript(options?: PantryBootstrapOptions): string[];
|
|
65
|
+
/**
|
|
66
|
+
* Shell snippet that puts the project's pantry-installed binaries (php,
|
|
67
|
+
* composer, …) on PATH for a deploy step. `pantry env` is project-scoped, so it
|
|
68
|
+
* is evaluated from {@link PANTRY_PROJECT_DIR}. Returns a single line to
|
|
69
|
+
* `eval`/source before invoking those binaries.
|
|
70
|
+
*/
|
|
71
|
+
export declare function pantryEnvActivation(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Install one or more pantry packages in a single resolve pass. Accepts known
|
|
74
|
+
* domains (optionally `domain@version`). Returns `[]` for an empty list.
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildPantryInstallScript(specs: readonly PantrySpec[]): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Enable (start on boot) and start pantry-managed services now. Service names
|
|
79
|
+
* are pantry's own (`'php-fpm'`, `'nginx'`, `'mysql'`, `'redis'`, …), not the
|
|
80
|
+
* package domains.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildPantryServiceScript(services: readonly string[]): string[];
|
|
83
|
+
/** Resolve a logical key (or an explicit domain) to its package domain. */
|
|
84
|
+
export declare function pantryDomain(pkg: PantryPackageKey | PantryPackageDomain): PantryPackageDomain;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The baseline Laravel PHP extensions. pantry's `php.net` is a single source
|
|
3
|
+
* build that already bundles these, so unlike apt there are no per-extension
|
|
4
|
+
* packages to install — this list documents the expectation and is asserted
|
|
5
|
+
* against `php -m` in tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare const LARAVEL_PHP_EXTENSIONS: readonly string[];
|
|
8
|
+
export interface PhpProvisionOptions {
|
|
9
|
+
/** PHP versions to install (first is the default). pantry runs one php-fpm. @default ['8.3'] */
|
|
10
|
+
versions?: string[];
|
|
11
|
+
/** Default PHP version. @default first of `versions` */
|
|
12
|
+
default?: string;
|
|
13
|
+
/** Extra extensions — informational; pantry's php build is fixed. */
|
|
14
|
+
extensions?: string[];
|
|
15
|
+
/** Install the nginx binary (the vhost/service is wired separately). @default true */
|
|
16
|
+
installNginx?: boolean;
|
|
17
|
+
/** Install Composer. @default true */
|
|
18
|
+
installComposer?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** PHP-FPM listen address for nginx `fastcgi_pass` (pantry's php-fpm is TCP). */
|
|
21
|
+
export declare const PHP_FPM_LISTEN = "127.0.0.1:9074";
|
|
22
|
+
/**
|
|
23
|
+
* php-fpm `fastcgi_pass` target. The `version` arg is accepted for API
|
|
24
|
+
* compatibility with the old per-version unix sockets; pantry runs a single
|
|
25
|
+
* php-fpm on {@link PHP_FPM_LISTEN}.
|
|
26
|
+
*/
|
|
27
|
+
export declare function phpFpmSocketPath(_version?: string): string;
|
|
28
|
+
/** Resolve the default PHP version from the requested set. */
|
|
29
|
+
export declare function resolveDefaultPhpVersion(options?: PhpProvisionOptions): string;
|
|
30
|
+
/**
|
|
31
|
+
* Build the shell command lines that install PHP-FPM + Composer (+ the nginx
|
|
32
|
+
* binary) via pantry and start php-fpm as a system service. Assumes the pantry
|
|
33
|
+
* CLI is already bootstrapped (see
|
|
34
|
+
* {@link import('./package-manager').buildPantryBootstrapScript}).
|
|
35
|
+
*/
|
|
36
|
+
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[];
|