From 0593bb1d3e7521dd0dc8c25b38243d302d67ed56 Mon Sep 17 00:00:00 2001 From: cggonzal Date: Wed, 24 Sep 2025 19:35:51 -0700 Subject: [PATCH 1/4] add deploy command to documentation --- .vitepress/config/en.ts | 4 + en/getting-started/deploy.md | 206 +++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 en/getting-started/deploy.md diff --git a/.vitepress/config/en.ts b/.vitepress/config/en.ts index 4f6d734bc..47dba7d7d 100644 --- a/.vitepress/config/en.ts +++ b/.vitepress/config/en.ts @@ -122,6 +122,10 @@ function sidebarQuickstart(): DefaultTheme.SidebarItem[] { text: 'Compile', link: 'compile' }, + { + text: 'Deploy', + link: 'deploy' + }, { text: 'Release Notes', link: 'releases' diff --git a/en/getting-started/deploy.md b/en/getting-started/deploy.md new file mode 100644 index 000000000..5aaa5504f --- /dev/null +++ b/en/getting-started/deploy.md @@ -0,0 +1,206 @@ +# Deploy + +[[toc]] + +## Overview + +The `deploy` command provides a simple, opinionated deployment pipeline for Goravel applications. It compiles your application locally, performs one-time remote server setup when needed, uploads application artifacts, restarts the service, and supports rollback to the previous binary. It is designed to offer a pragmatic, single-command deploy suitable for small-to-medium workloads. + +Key capabilities: +- Builds a target binary for your chosen OS/ARCH (optionally statically linked) +- First-time remote provisioning with systemd and optional Caddy reverse proxy +- Uploads binary, `.env`, and optional `public/`, `storage/`, `resources/` directories +- Restarts the systemd service +- Rollback support for the previously deployed binary + +## Quick start + +### With reverse proxy (recommended) + +Prepare a production `.env` (for example `.env.production`) with at least: + +``` +APP_NAME=my-app +DEPLOY_IP_ADDRESS=127.0.0.1 +DEPLOY_APP_PORT=9000 +DEPLOY_SSH_PORT=22 +DEPLOY_SSH_USER=deploy +DEPLOY_SSH_KEY_PATH=~/.ssh/id_rsa +DEPLOY_OS=linux +DEPLOY_ARCH=amd64 +DEPLOY_PROD_ENV_FILE_PATH=.env.production +DEPLOY_STATIC=true +DEPLOY_REVERSE_PROXY_ENABLED=true +DEPLOY_REVERSE_PROXY_TLS_ENABLED=true +DEPLOY_DOMAIN=my-app.com +``` + +Then run: + +``` +go run . artisan deploy +``` + +This will: +1. Build the application. +2. On the server: install and configure Caddy as a reverse proxy, optionally enable TLS with automatic certificates, and expose HTTP(S) to your domain. +3. Configure ufw firewall to allow required traffic. +4. Create and enable a systemd unit for your app. +5. Upload the binary, environment file, and optional assets. +6. Restart the systemd service. + +### Without reverse proxy + +For a simpler deployment without a reverse proxy, use: + +``` +APP_NAME=my-app +DEPLOY_IP_ADDRESS=127.0.0.1 +DEPLOY_APP_PORT=80 +DEPLOY_SSH_PORT=22 +DEPLOY_SSH_USER=deploy +DEPLOY_SSH_KEY_PATH=~/.ssh/id_rsa +DEPLOY_OS=linux +DEPLOY_ARCH=amd64 +DEPLOY_PROD_ENV_FILE_PATH=.env.production +DEPLOY_STATIC=true +DEPLOY_REVERSE_PROXY_ENABLED=false +DEPLOY_REVERSE_PROXY_TLS_ENABLED=false +DEPLOY_DOMAIN= +``` + +Run: + +``` +go run . artisan deploy +``` + +This will: +1. Build the application. +2. On the server: configure ufw firewall for HTTP on port 80. +3. Create and enable the systemd unit. +4. Upload the binary, environment file, and optional assets. +5. Restart the service. + +### Rollback + +Revert to the previously deployed binary: + +``` +go run . artisan deploy --rollback +``` + +### Force setup + +Re-apply provisioning (e.g., after changing proxy/TLS/domain): + +``` +go run . artisan deploy --force-setup +``` + +### Deploy only a subset of files + +Upload only specific artifacts (e.g., binary and `.env`): + +``` +go run . artisan deploy --only main,env +``` + +## Architecture assumptions + +Two topologies are supported: + +1) Reverse proxy (recommended) +- `DEPLOY_REVERSE_PROXY_ENABLED=true` +- App listens on `127.0.0.1:` (e.g. 9000) +- Caddy proxies public HTTP(S) to the app +- If `DEPLOY_REVERSE_PROXY_TLS_ENABLED=true` and `DEPLOY_DOMAIN` is set, Caddy terminates TLS and manages certificates; otherwise Caddy serves plain HTTP on `:80` + +2) No reverse proxy +- `DEPLOY_REVERSE_PROXY_ENABLED=false` +- App listens directly on `:80` (`APP_HOST=0.0.0.0`, `APP_PORT=80`) + +## Artifacts and server layout + +Remote base directory: `/var/www/` + +Managed files: +- `main`: current binary +- `main.prev`: previous binary (for rollback) +- `.env`: uploaded from `DEPLOY_PROD_ENV_FILE_PATH` +- `public/`: optional static assets +- `storage/`: optional storage directory +- `resources/`: optional resources directory + +## First-time setup and idempotency + +On the first deploy, the command checks for `/etc/systemd/system/.service`. If absent, it will: +- Install and configure Caddy (when reverse proxy is enabled) +- Create the app directory and set ownership +- Write the systemd unit and enable the service +- Configure ufw firewall rules + +Subsequent deploys skip setup for speed and safety. Use `--force-setup` to re-apply provisioning changes. + +## Systemd service + +- Runs under `DEPLOY_SSH_USER` +- Provides `APP_HOST` and `APP_PORT` via environment +- Working directory is `/var/www/` +- Uses restarts (brief downtime). For zero-downtime, adopt a more advanced process manager or socket activation + +## Security and firewall + +- SSH uses `StrictHostKeyChecking=no` for convenience. For production, consider pre-trusting the host key +- Firewall rules are applied via ufw: allow OpenSSH and required HTTP(S) ports first, then enable ufw to avoid losing SSH connectivity + +## High-level deployment flow + +1. Build: compile the binary for the specified target (OS/ARCH, optional static) with name `APP_NAME` +2. Determine artifacts to upload: `main`, `.env`, `public`, `storage`, `resources` (filterable via `--only`) +3. First-time setup or `--force-setup`: directories, Caddy (optional), systemd unit, ufw rules +4. Upload: binary and assets (atomic swaps for binary and `.env`, backups retained as `*.prev`) +5. Restart service: daemon-reload then restart (or start) + +## Known limitations + +- No database migrations or orchestration is performed +- Rollback swaps the binary (and restores backed-up assets when present) but does not re-run migrations +- `StrictHostKeyChecking` is disabled by default +- Changing proxy/TLS/domain requires `--force-setup` +- Assumes Debian/Ubuntu with `apt-get` and `ufw` + +## Configuration + +These environment variables control the deploy command. Set them in your production `.env` file. + +### Required + +- `app.name`: Application name; used for remote paths and systemd service name +- `DEPLOY_IP_ADDRESS`: Target server IP address +- `DEPLOY_APP_PORT`: Backend app port when reverse proxy is used (e.g. `9000`). If no reverse proxy, the app listens on `80` +- `DEPLOY_SSH_PORT`: SSH port (e.g. `22`) +- `DEPLOY_SSH_USER`: SSH username (must have sudo privileges) +- `DEPLOY_SSH_KEY_PATH`: Path to SSH private key (e.g. `~/.ssh/id_rsa`) +- `DEPLOY_OS`: Target OS for build (e.g. `linux`) +- `DEPLOY_ARCH`: Target architecture for build (e.g. `amd64`) +- `DEPLOY_PROD_ENV_FILE_PATH`: Local path to the production `.env` file to upload + +### Optional / boolean (default false if unset) + +- `DEPLOY_STATIC`: Build statically when `true` +- `DEPLOY_REVERSE_PROXY_ENABLED`: Use Caddy reverse proxy when `true` +- `DEPLOY_REVERSE_PROXY_TLS_ENABLED`: Enable TLS (requires `DEPLOY_DOMAIN`) when `true` +- `DEPLOY_DOMAIN`: Domain name for TLS or HTTP vhost when using Caddy (required only if TLS is enabled) + +### CLI flags + +- `--only`: Comma-separated subset to deploy: `main,env,public,storage,resources` +- `-r, --rollback`: Roll back to previous deployment +- `-F, --force-setup`: Force re-run server setup even if already configured + +## Local build and artifacts + +The deploy command compiles your application using the given target OS/ARCH and static preferences. For background and manual alternatives, see `Compile`: + +`https://www.goravel.dev/getting-started/compile.html` From 3d4eec00055883c0f6e7ca62ec6ed272368d5084 Mon Sep 17 00:00:00 2001 From: cggonzal Date: Wed, 24 Sep 2025 21:14:30 -0700 Subject: [PATCH 2/4] add A record note --- en/getting-started/deploy.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/en/getting-started/deploy.md b/en/getting-started/deploy.md index 5aaa5504f..573f52809 100644 --- a/en/getting-started/deploy.md +++ b/en/getting-started/deploy.md @@ -35,6 +35,8 @@ DEPLOY_REVERSE_PROXY_TLS_ENABLED=true DEPLOY_DOMAIN=my-app.com ``` +> Note: Ensure your domain registrar has a DNS A record for `DEPLOY_DOMAIN` pointing to `DEPLOY_IP_ADDRESS` (and an AAAA record if using IPv6). Caddy can only issue certificates when the domain resolves to your server's IP. + Then run: ``` From c5d0b4f8d69dda33f043ce71c1686a742d6ccda1 Mon Sep 17 00:00:00 2001 From: cggonzal Date: Thu, 25 Sep 2025 20:38:58 -0700 Subject: [PATCH 3/4] add request flow section to docs --- en/getting-started/deploy.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/en/getting-started/deploy.md b/en/getting-started/deploy.md index 573f52809..a82a81deb 100644 --- a/en/getting-started/deploy.md +++ b/en/getting-started/deploy.md @@ -51,6 +51,14 @@ This will: 5. Upload the binary, environment file, and optional assets. 6. Restart the systemd service. +#### Request flow + +1. User sends HTTP(S) request to `DEPLOY_DOMAIN`. +2. Caddy receives the request and proxies to `127.0.0.1:DEPLOY_APP_PORT`. +3. Goravel app processes the request (routing, middleware, controller). +4. App returns a response to Caddy. +5. Caddy sends the HTTP(S) response back to the user. + ### Without reverse proxy For a simpler deployment without a reverse proxy, use: @@ -84,6 +92,12 @@ This will: 4. Upload the binary, environment file, and optional assets. 5. Restart the service. +#### Request flow + +1. User sends HTTP request to `APP_HOST:APP_PORT` (e.g., `0.0.0.0:80`). +2. Goravel app processes the request (routing, middleware, controller). +3. App sends the HTTP response back to the user. + ### Rollback Revert to the previously deployed binary: From 6dea0649a1b1b0697eb68a2f062bf549550e8791 Mon Sep 17 00:00:00 2001 From: cggonzal Date: Sun, 26 Oct 2025 12:40:52 -0700 Subject: [PATCH 4/4] update documentation to match latest .env file definitions for deploy command --- en/getting-started/deploy.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/en/getting-started/deploy.md b/en/getting-started/deploy.md index a82a81deb..8958e765a 100644 --- a/en/getting-started/deploy.md +++ b/en/getting-started/deploy.md @@ -21,8 +21,8 @@ Prepare a production `.env` (for example `.env.production`) with at least: ``` APP_NAME=my-app -DEPLOY_IP_ADDRESS=127.0.0.1 -DEPLOY_APP_PORT=9000 +APP_PORT=9000 +DEPLOY_SSH_IP=127.0.0.1 DEPLOY_SSH_PORT=22 DEPLOY_SSH_USER=deploy DEPLOY_SSH_KEY_PATH=~/.ssh/id_rsa @@ -65,8 +65,8 @@ For a simpler deployment without a reverse proxy, use: ``` APP_NAME=my-app -DEPLOY_IP_ADDRESS=127.0.0.1 -DEPLOY_APP_PORT=80 +APP_PORT=80 +DEPLOY_SSH_IP=127.0.0.1 DEPLOY_SSH_PORT=22 DEPLOY_SSH_USER=deploy DEPLOY_SSH_KEY_PATH=~/.ssh/id_rsa