Skip to content

feat: allow deploying to hetzner#1432

Open
tefkah wants to merge 152 commits intomainfrom
tfk/hetzner-host
Open

feat: allow deploying to hetzner#1432
tefkah wants to merge 152 commits intomainfrom
tfk/hetzner-host

Conversation

@tefkah
Copy link
Copy Markdown
Member

@tefkah tefkah commented Apr 2, 2026

Issue(s) Resolved

Deploy to hetzner instead of s3 a la v6

High-level Explanation of PR

  • Pushes all images to ghcr instead of ECR
  • Uses hetzner box to deploy preview images on open preview
  • Uses hetzner box to deploy sandbox
  • Uses hetzner box to deploy prod

Deploy schedule

Preview

Open: when adding preview label to pr
Close: when closing/merging pr, or removal of preview label
Update: Is reset every 6 hours by https://github.com/knowledgefutures/pubplatform/blob/24d4b4d49cbce3a6a520db5d7e6ecc7ac3bc49e5/.github/workflows/reset-preview-envs.yml
Where: https://pr-xxxx.pubstar.org, will be put in comment on first deploy

Sandbox

Open: always
Close: never
Update: on merge with main, every 6 hours like preview, or manual update through https://github.com/knowledgefutures/pubplatform/blob/291ecf00d2f939128504803d11e8453931f347ea/.github/workflows/deploy-manual.yml
Where: sandbox.pubstar.org

Tip: use gh workflow run deploy-manual.yml --ref <branch> -f environment=sandbox to force a sandbox update from a specific branch

Prod

Update: when doing manual deploy, or when pushing a tag with a vx.x.x format
Where: app.pubstar.org

Changes

  • Added /superadmin

    • Can set backup schedule there
    • Can look at migrations there
  • changed deps slightly

    • Use postgres 17 for db vs inconsistent 14 (prod) 15 (dev) 16 (preview/sandbox)
    • Use node 22->24
    • Alpine 3.20->3.22
  • stack changes

    • no more migrations container, migrations run at startup of core, set DB_SEED=1 and DB_RESET=1 to seed and reset respectively
    • added sitebuilder and mock notify containers. mock notify is only accessible on sandbox/preview
    • allowed sandbox/preview to have image uploads, sending emails, and limited http action use (only to localhost or pubstar.org domains). emails are send to inbucket, uploads are handled locally

Test Plan

Screenshots (if applicable)

Notes

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the repo’s CI/build/deploy pipeline from AWS ECR/ECS + PullPreview to GHCR + SSH-based Docker Swarm deployments on Hetzner, and introduces SOPS-managed env files plus Caddy-based proxying for preview and production stacks.

Changes:

  • Replace ECR build workflows with GHCR build workflows and update e2e to pull images from GHCR.
  • Replace PullPreview-based preview deployments with an SSH-driven Swarm stack deploy/teardown workflow.
  • Add Hetzner deployment workflow + new Swarm stack/Caddy/SOPS infra assets.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
package.json Adds SOPS encrypt/decrypt helper scripts.
infra/stack.yml New Swarm stack definition for non-preview deployments.
infra/stack.preview.yml New Swarm stack definition for PR previews (includes MinIO, init).
infra/import-backup.sh Adds a helper to import DB dumps into the Swarm DB container.
infra/Caddyfile.preview Adds preview Caddy config (on-demand TLS, routes).
infra/Caddyfile Adds prod/staging Caddy config (routes to platform/site-builder/assets).
infra/.sops.yaml Adds SOPS rules for encrypted env files.
infra/.env.preview.enc Adds encrypted preview env file.
infra/.env.example Adds infra env template for prod-like deployments.
docker-compose.preview.yml Removes old PullPreview compose definition.
docker-compose.preview.sandbox.yml Removes old PullPreview sandbox override.
docker-compose.preview.pr.yml Removes old PullPreview PR override.
.gitignore Ignores decrypted infra env files and keeps encrypted env tracked.
.github/workflows/pull-preview.yml Removes PullPreview workflow.
.github/workflows/pull-preview-script.sh Removes PullPreview helper script.
.github/workflows/preview.yml Adds SSH-based PR preview deploy/teardown workflow.
.github/workflows/on_pr.yml Switches PR pipeline to GHCR builds + new preview workflow.
.github/workflows/on_main.yml Switches main pipeline to GHCR builds and removes AWS deploy steps.
.github/workflows/ghcr-build-template.yml Adds reusable GHCR build/push workflow.
.github/workflows/ghcr-build-all.yml Adds GHCR build-all aggregator workflow.
.github/workflows/ecrbuild-template.yml Removes ECR build template workflow.
.github/workflows/ecrbuild-all.yml Removes ECR build-all workflow.
.github/workflows/e2e.yml Updates e2e to pull images from GHCR and adjusts permissions.
.github/workflows/deploy.yml Adds Hetzner deploy workflow (build + SSH deploy).
.github/workflows/deploy-template.yml Removes ECS deploy template workflow.
.github/workflows/awsdeploy.yml Removes ECS deploy orchestrator workflow.
.env.example Adds a base env example for local/dev/self-hosting defaults.
Comments suppressed due to low confidence (1)

infra/stack.yml:154

  • stack.yml configures Caddy to proxy /assets* and /assets-ui* to minio:9000/9001 (see infra/Caddyfile), but this stack doesn't define a minio service. As-is, asset routes will 502 and site serving via the fs s3 plugin will fail. Add a minio service (and any init/bucket/user bootstrap you need) or remove the MinIO proxies and the unused minio_data volume.
volumes:
  pgdata:
  minio_data:
  caddy_data:
  caddy_config:


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread infra/Caddyfile
Comment thread infra/Caddyfile.preview Outdated
Comment thread infra/Caddyfile.preview Outdated
Comment thread infra/stack.preview.yml Outdated
Comment thread infra/Caddyfile.preview Outdated
Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/ghcr-build-template.yml Outdated
Comment thread .github/workflows/deploy.yml Outdated
Comment thread infra/import-backup.sh
Comment on lines +19 to +27
echo "importing $DUMP_FILE into container $DB_CONTAINER ..."

if [[ "$DUMP_FILE" == *.sql ]]; then
sudo docker exec -i "$DB_CONTAINER" \
psql -U "$PGUSER" -d "$PGDATABASE" < "$DUMP_FILE"
else
sudo docker exec -i "$DB_CONTAINER" \
pg_restore --clean --if-exists --no-owner -U "$PGUSER" -d "$PGDATABASE" < "$DUMP_FILE"
fi
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script uses set -u but relies on PGUSER/PGDATABASE being set in the environment. If the caller hasn't exported them, the script will exit with an unbound-variable error before running psql/pg_restore. Consider sourcing infra/.env (or accepting --pguser/--pgdatabase flags / defaulting to POSTGRES_USER/POSTGRES_DB) and validating the required values up-front.

Copilot uses AI. Check for mistakes.
@tefkah tefkah added the preview Auto-deploys a preview application label Apr 2, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 2, 2026

Preview deployed at https://pr-1432.pubstar.org

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 29, 2026

PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://knowledgefutures.github.io/pubplatform/pr-preview/pr-1432/

Built to branch gh-pages at 2026-04-30 19:58 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Auto-deploys a preview application

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants