Self-hosting is a great way to have control over your deployment infrastructure (you own the data) and a great way to keep the costs down (you pay a fixed amount per month). One of the well established ways to manage your self-hosted deployment is Caprover.
Deploying Wasp apps to Caprover is straightforward:
- create your Caprover apps (client, server and db)
- build your app's Docker images (e.g. using Github Actions),
- trigger Caprover to pull the Docker images and deploy them.
It'll take you ~1 hour depending on your level of experience with servers and Github Actions.
You should have Caprover installed and set up on your server. I'll be using Hetzner to rent my server.
Follow the Caprover install instructions: https://caprover.com/docs/get-started.html#prerequisites
Note
Following the install instructions, I've pointed an A record with value *.apps to my server IP. This gives me https://captain.apps.mydomain.com as my Caprover URL and enables me to have quick sub-domains i.e. https://<app-name>.apps.mydomain.com for testing stuff out.
To get Caprover apps working with your domain - you'll need to point a A record to your server IP:
-
To use
myapp.comas your client domain, point theArecord with the value of@to your server IP. -
To use
api.myapp.comas your server domain, point theArecord with the value ofapito your server IP.
We'll set up the domains for our server and client apps below.
- Create a new one-click app, select
PostgreSQL- Name it
myapp-db - Enter the version to be one the latest version e.g.
17 - Deploy it
- Write down the connection string based on the info you get:
postgresql://postgres:<password>@srv-captain--myapp-db:5432/postgres(srv-captain--myapp-dbis based on the DB app name)
- Name it
- Create a new app named
myapp-server- Connect a new domain as
https://api.<your-domain> - Press
Enable HTTPSfor the domain - Set the
Container HTTP Portto3001 - Enable
Force HTTPS by redirecting all HTTP traffic to HTTPSandWebsocket Support - Make sure to hit the
Save & Restartbutton after you change stuff
- Connect a new domain as
- Create a new app named
myapp-client- Connect a new domain as
https://<your-domain> - Press
Enable HTTPSfor the domain - Set the
Container HTTP Portto8043 - Enable
Force HTTPS by redirecting all HTTP traffic to HTTPSandWebsocket Support - Make sure to hit the
Save & Restartbutton after you change stuff
- Connect a new domain as
Let's go back into the server app and configure the required env vars:
- Go under
App ConfigsandEnvironment Variables - Add the following env vars:
DATABASE_URLwith value of the database connection stringJWT_SECRETgenerate it with some online generatorPORTset it to3001WASP_WEB_CLIENT_URLset it tohttps://<your-domain>WASP_SERVER_URLset it tohttps://api.<your-domain>
- Add any other env vars you might have defined locally in the
.env.serverfile
- In your app root dir create a new
.githubfolder - Inside of
.githubfolder, create a newworkflowsfolder - Copy the
deploy.ymlfile from this gist to theworkflowsfolder
Once you copy the deploy.yml, make sure to modify the:
WASP_VERSIONenv varSERVER_APP_NAMEenv var - this will be used in the Docker image nameSERVER_APP_URLenv varCLIENT_APP_NAMEenv var - this will be used in the Docker image name
The DOCKER_REGISTRY, DOCKER_REGISTRY_USERNAME and DOCKER_REGISTRY_PASSWORD env vars will work out of the box for Github Container Registry.
Warning
If your app is located in the app folder (e.g. Open Saas has the app in the app folder) you can use the action as-is.
If your app is not in the app folder, follow the comments on lines 70, 87, 89, 98 and 100 to modify some paths.
The Github Action depends on some repository secrets to work properly - these are some values that can't be public. You add them by going into your repository Settings and then find Secrets and variables and select Actions.
Let's add the:
CAPROVER_SERVERsecret- Write your dashboard URL e.g.
https://captain.apps.mydomain.com
- Write your dashboard URL e.g.
SERVER_APP_TOKENsecret- Go to your
serverapp - Under
DeploymentfindMethod 1: Official CLI - Press
Enable App Token - Paste it as the secret value
- Go to your
CLIENT_APP_TOKENsecret- Go to your
clientapp - Under
DeploymentfindMethod 1: Official CLI - Press
Enable App Token - Paste it as the secret value
- Go to your
- Under
Clusterin Caprover add a new Remote Registry - Set
Usernameto your Github username - Set
Passwordto your Github token - Set
Domaintoghcr.io - Set
Image Prefixto your Github username
You can move your domain's nameservers to Cloudflare to get the benefits of their CDN and DDoS protections.
I've had to keep my A record with the value *.apps as DNS Only since Cloudflare doesn't do multiple level free SSL. But I use Full SSL for the custom domains.
For me the Caprover option
Enable Force HTTPS by redirecting all HTTP traffic to HTTPS and Websocket Supportwas causing redirect issues after deploying, once disabled the app worked properly but still was throwing CORS issues.I solved them by adding:
and