{"id":23034246,"url":"https://github.com/guillempuche/selfhost_fullstack_in_vps","last_synced_at":"2025-04-23T17:28:50.901Z","repository":{"id":265840619,"uuid":"894156329","full_name":"guillempuche/selfhost_fullstack_in_vps","owner":"guillempuche","description":"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.","archived":false,"fork":false,"pushed_at":"2025-01-17T10:32:17.000Z","size":588,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-19T08:55:46.338Z","etag":null,"topics":["coolify","docker-compose","hetzner-cloud","postgresql","powersync","supertokens","traefik","vps"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guillempuche.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-25T21:17:50.000Z","updated_at":"2025-04-18T00:56:37.000Z","dependencies_parsed_at":"2024-12-02T01:03:05.853Z","dependency_job_id":null,"html_url":"https://github.com/guillempuche/selfhost_fullstack_in_vps","commit_stats":null,"previous_names":["guillempuche/selfhost_fullstack_in_vps"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillempuche%2Fselfhost_fullstack_in_vps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillempuche%2Fselfhost_fullstack_in_vps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillempuche%2Fselfhost_fullstack_in_vps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillempuche%2Fselfhost_fullstack_in_vps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guillempuche","download_url":"https://codeload.github.com/guillempuche/selfhost_fullstack_in_vps/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250479907,"owners_count":21437455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coolify","docker-compose","hetzner-cloud","postgresql","powersync","supertokens","traefik","vps"],"created_at":"2024-12-15T16:30:38.683Z","updated_at":"2025-04-23T17:28:50.881Z","avatar_url":"https://github.com/guillempuche.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VPS\n\nEmpower your software hosting it on a VPS (Virtual Private Server). Cheaper and portable.\n\nIf you want to replicate your localhost to staging/production, you can use this guide.\n\nSelf-hosted TypeScript apps I'm using:\n\n- [Web] Vite React (\u003cwww.yourdomain.com\u003e)\n- [Server] NodeJS (api.yourdomain.com)\n\nSelf-hosted services I'm using:\n\n- [VPS] Hetzner\n- [Git] GitHub\n- [Deployment] Coolify\n- [Database] Postgres\n- [Local-Cloud Sync] PowerSync\n- [Auth] Supertokens\n\nOther services:\n\n- [Reverse Proxy] Traefik (configured in Coolify)\n- [DNS, TLS, Protection] Cloudflare\n- [Email] Docker Inbucket for local development (not VPS)\n- [Postgres Migration] Flyway\n\nFor Postgres migration, I'm using [Flyway](https://flywaydb.org/).\n\n## Content Table\n\n- [0. Pre-requisites](#0-pre-requisites)\n- [1. Create The Services Locally](#1-create-the-services-locally)\n- [2. Setup VPS](#2-setup-vps)\n- [3. Setup DNS \u0026 TLS](#3-setup-dns-tls)\n- [4. Setup Coolify](#4-setup-coolify)\n- [5. Deploy the Services to the VPS](#5-deploy-the-services-to-the-vps)\n\n## [0. Pre-requisites](#0-pre-requisites)\n\n1. [Local] Install on your laptop [Deno](https://deno.land/)\n2. [Local] Install on your laptop [Docker Desktop](https://www.docker.com/products/docker-desktop/) or other, like [OrbStack](https://orbstack.dev/).\n3. [Local] Configure `.env` files for your services (see `services/postgres/.env` for example)\n4. Your domain connected to Cloudflare.\n\n## [1. Create The Services Locally](#1-create-the-services-locally)\n\nThe 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:\n\n- **Postgres**: Main database for the application\n- **PowerSync**: Data synchronization service with MongoDB\n- **Supertokens**: Authentication service\n- **Email**: Local email testing with Inbucket\n\nAll services are managed through Deno tasks for consistent command execution:\n\n```bash\n# Important: Run all commands from the root directory of the project\n# cd scripts/services\n\n# Start all services\ndeno task docker:up\n\n# Start specific services\ndeno task docker:up postgres\ndeno task docker:up email powersync\n\n# Stop all services\ndeno task docker:down\n\n# Restart services\ndeno task docker:restart\n\n# Clean volumes\ndeno task docker:clean          # Clean all volumes\ndeno task docker:clean postgres # Clean specific service volumes\n\n# Setup PowerSync (usually automatic)\ndeno task docker:setup_powersync\n```\n\n### Services Structure\n\nServices are defined in `scripts/services/types.ts`:\n\n- `email`\n- `postgres`\n- `powersync`\n- `supertokens`\n\n### Important Notes\n\n1. Services start in a specific order to handle dependencies\n2. When starting `postgres`, PowerSync setup runs automatically\n3. All commands are idempotent - safe to run multiple times\n4. Health checks run automatically to verify service status\n\n## [2. Setup The VPS](#2-setup-the-vps)\n\n1. [Create VPS on Hetzner](https://docs.hetzner.com/cloud/servers/getting-started/creating-a-server) (cheaper than AWS; [link 2](https://tech.ahrefs.com/how-ahrefs-saved-us-400m-in-3-years-by-not-going-to-the-cloud-8939dd930af8). [link 2](https://learn.umh.app/course/aws-and-azure-are-at-least-4x-10x-more-expensive-than-hetzner/)). Debian.\n2. Connect to your Hetzner VPS with SSH. Guide \u003chttps://docs.hetzner.com/cloud/servers/getting-started/connecting-to-the-server/\u003e\n3. Update and upgrade Debian packages.\n\n```bash\nsudo apt update \u0026\u0026 sudo apt upgrade -y\n```\n\n## [3. Setup DNS \u0026 TLS](#3-setup-dns-tls)\n\n[!CAUTION] Work in progress\n\n1. Enable TLS Strict mode on Cloudflare \u003chttps://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/\u003e\n2. Create a Cloudflare Origin CA \u003chttps://developers.cloudflare.com/ssl/origin-configuration/origin-ca/\u003e\n3. Setup a DNS record for your domain pointing to your VPS.\n4. Obtain API Token from Cloudflare and update Traefik .env\n\n\u003cimg src=\"assets/cloudflare_dns.png\" alt=\"Cloudflare DNS\" width=\"600\" /\u003e\n\n## [4. Setup Coolify](#4-setup-coolify)\n\nUse cloud or self-hosted. I'm using the cloud (only $5/month).\n\n1. Create a Coolify account.\n2. Create a new server in an Staging or Production environment. My case is Staging.\n\n   \u003cimg src=\"assets/coolify_server.png\" alt=\"Coolify server\" height=\"300\" /\u003e\n\n3. Create a SSH key automatically with the \"Generate new Ed25519 SSH key\" function.\n\n   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).\n\n   \u003cimg src=\"assets/coolify_ssh_1.png\" alt=\"Coolify ssh step 1\" width=\"600\" /\u003e\n   \u003cimg src=\"assets/coolify_ssh_2.png\" alt=\"Coolify ssh step 2\" width=\"600\" /\u003e\n\n4. 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.\n5. Create a source with GitHub Apps to connect Coolify to your repository.\n\n   \u003cimg src=\"assets/coolify_sources.png\" alt=\"Coolify sources\" width=\"600\" /\u003e\n\n## [5. Deploy the Services to the VPS](#5-deploy-the-services-to-the-vps)\n\n1. Create a new resource on Coolify via the source you created in the previous step (GitHub Apps).\n\n   \u003cimg src=\"assets/coolify_resources_1.png\" alt=\"Coolify resources step 1\" width=\"600\" /\u003e\n\n2. Select (Docker Compose instead of Nixpacks). Remember to write the branch you want to deploy.\n\n   \u003cimg src=\"assets/coolify_resources_2.png\" alt=\"Coolify resources step 2\" width=\"600\" /\u003e\n\n3. Check `.env.example` of this repo `Environment Variables` of the resource --\u003e `Production`. Add the missing variables to Coolify.\n\n4. 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.\n\n   ```bash\n   docker network create backend_network\n   ```\n\n5. Deploy the service.\n\n6. Do this for each service (PowerSync, Supertokens, Postgres).\n\n## Troubleshooting\n\n### Local Development\n\n1. Check Docker logs: `docker logs \u003ccontainer_name\u003e`\n2. Verify environment variables in service `.env` files\n3. Use `deno task docker:down` followed by `deno task docker:up` to reset services\n4. Clean volumes if database issues occur: `deno task docker:clean`\n\n### VPS Deployment\n\n1. Check Coolify logs for deployment issues\n2. Verify network configuration\n3. Ensure all environment variables are set correctly\n4. Check Cloudflare DNS and SSL/TLS settings\n\n## Todo\n\n- Web and server sample apps.\n- Add Traefik for reverse proxy to Coolify.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguillempuche%2Fselfhost_fullstack_in_vps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguillempuche%2Fselfhost_fullstack_in_vps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguillempuche%2Fselfhost_fullstack_in_vps/lists"}