Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A practical guide for hosting self-managed TypeScript apps on a VPS, with tools like Coolify, Postgres, PowerSync, and Supertokens. Learn to set up services locally, configure Hetzner VPS, secure with Cloudflare, and deploy seamlessly. Ideal for replicating localhost setups to staging/production.

Notifications You must be signed in to change notification settings

guillempuche/selfhost_fullstack_in_vps

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

8 Commits

Repository files navigation

VPS

Empower your software hosting it on a VPS (Virtual Private Server). Cheaper and portable.

If you want to replicate your localhost to staging/production, you can use this guide.

Self-hosted TypeScript apps I'm using:

Self-hosted services I'm using:

  • [VPS] Hetzner
  • [Git] GitHub
  • [Deployment] Coolify
  • [Database] Postgres
  • [Local-Cloud Sync] PowerSync
  • [Auth] Supertokens

Other services:

  • [Reverse Proxy] Traefik (configured in Coolify)
  • [DNS, TLS, Protection] Cloudflare
  • [Email] Docker Inbucket for local development (not VPS)
  • [Postgres Migration] Flyway

For Postgres migration, I'm using Flyway.

Content Table

  1. [Local] Install on your laptop Deno
  2. [Local] Install on your laptop Docker Desktop or other, like OrbStack.
  3. [Local] Configure .env files for your services (see services/postgres/.env for example)
  4. Your domain connected to Cloudflare.

The local development environment uses Docker Compose to run multiple services. Each service is defined in its own directory under services/ with its configuration files. The services include:

  • Postgres: Main database for the application
  • PowerSync: Data synchronization service with MongoDB
  • Supertokens: Authentication service
  • Email: Local email testing with Inbucket

All services are managed through Deno tasks for consistent command execution:

# Important: Run all commands from the root directory of the project
# cd scripts/services
# Start all services
deno task docker:up
# Start specific services
deno task docker:up postgres
deno task docker:up email powersync
# Stop all services
deno task docker:down
# Restart services
deno task docker:restart
# Clean volumes
deno task docker:clean # Clean all volumes
deno task docker:clean postgres # Clean specific service volumes
# Setup PowerSync (usually automatic)
deno task docker:setup_powersync

Services Structure

Services are defined in scripts/services/types.ts:

  • email
  • postgres
  • powersync
  • supertokens

Important Notes

  1. Services start in a specific order to handle dependencies
  2. When starting postgres, PowerSync setup runs automatically
  3. All commands are idempotent - safe to run multiple times
  4. Health checks run automatically to verify service status
  1. Create VPS on Hetzner (cheaper than AWS; link 2. link 2). Debian.
  2. Connect to your Hetzner VPS with SSH. Guide https://docs.hetzner.com/cloud/servers/getting-started/connecting-to-the-server/
  3. Update and upgrade Debian packages.
sudo apt update && sudo apt upgrade -y

[!CAUTION] Work in progress

  1. Enable TLS Strict mode on Cloudflare https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/
  2. Create a Cloudflare Origin CA https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/
  3. Setup a DNS record for your domain pointing to your VPS.
  4. Obtain API Token from Cloudflare and update Traefik .env

Cloudflare DNS

Use cloud or self-hosted. I'm using the cloud (only 5ドル/month).

  1. Create a Coolify account.

  2. Create a new server in an Staging or Production environment. My case is Staging.

    Coolify server
  3. Create a SSH key automatically with the "Generate new Ed25519 SSH key" function.

    To allow Coolify to connect to your VPS, you need to create a SSH key. I prefer to use a different one than my laptop (in step #1).

    Coolify ssh step 1 Coolify ssh step 2
  4. I'm using the root user automatically created by the VPS. Note that this is not recommended for production. Coolify has a beta feature to allow other users.

  5. Create a source with GitHub Apps to connect Coolify to your repository.

    Coolify sources
  1. Create a new resource on Coolify via the source you created in the previous step (GitHub Apps).

    Coolify resources step 1
  2. Select (Docker Compose instead of Nixpacks). Remember to write the branch you want to deploy.

    Coolify resources step 2
  3. Check .env.example of this repo Environment Variables of the resource --> Production. Add the missing variables to Coolify.

  4. Create Docker network (found in docker-compose.yaml files) in the VPS using SSH terminal. This is to allow the services to communicate with each other.

    docker network create backend_network
  5. Deploy the service.

  6. Do this for each service (PowerSync, Supertokens, Postgres).

Troubleshooting

Local Development

  1. Check Docker logs: docker logs <container_name>
  2. Verify environment variables in service .env files
  3. Use deno task docker:down followed by deno task docker:up to reset services
  4. Clean volumes if database issues occur: deno task docker:clean

VPS Deployment

  1. Check Coolify logs for deployment issues
  2. Verify network configuration
  3. Ensure all environment variables are set correctly
  4. Check Cloudflare DNS and SSL/TLS settings

Todo

  • Web and server sample apps.
  • Add Traefik for reverse proxy to Coolify.

About

A practical guide for hosting self-managed TypeScript apps on a VPS, with tools like Coolify, Postgres, PowerSync, and Supertokens. Learn to set up services locally, configure Hetzner VPS, secure with Cloudflare, and deploy seamlessly. Ideal for replicating localhost setups to staging/production.

Topics

Resources

Stars

Watchers

Forks

AltStyle によって変換されたページ (->オリジナル) /