Before you begin
- A Sevalla company with a payment method, and a GitHub, GitLab or Bitbucket account for the repository. See Git providers.
- Node.js 22.16 or later on your computer, to generate the encryption key.
Use the example repository
The EmDash template for Sevalla is EmDash’s blog template with the hosting layer adapted to Sevalla:
Create an empty repository on your Git provider, such as
acme/storefront, then copy the template into it and generate the key that encrypts EmDash’s plugin secrets:
EMDASH_ENCRYPTION_KEY in the deployment steps, and EmDash can’t read its stored secrets without it.
Prepare the project for Sevalla
The template needs no code changes. Its parts depend on four Sevalla services, which you create in Deploy to Sevalla in the same location, because an internal connection only works within one location:- A PostgreSQL database. The database user that Sevalla creates owns the database, which EmDash needs because it creates and alters its own tables.
- The application, built with the Dockerfile build strategy.
- An object storage bucket with public access and a CORS rule, so the admin panel can upload from the browser.
- An API key that can update the application, used to purge the edge cache.
Deploy to Sevalla
1
Create the database
In the sidebar, click Databases, then click Create database. Under Database, choose PostgreSQL and version 16 or newer. Enter
orders-db as the Display name, choose a Data center and a Size, then click Create database. See Create a database for every field.2
Create the application
In the sidebar, click Applications, then click Create > Application. Under Source, click Private repository, then choose the Git provider, the Repository and the Branch. Under Location, choose the same Data center as the database. Keep the Size at H1 or choose a larger one, then click Create application. The application opens on its Overview tab with the status Not deployed yet: creating an application doesn’t deploy it.
3
Set the build strategy
Click the Settings tab, then click Update build strategy. Choose Dockerfile, keep the Dockerfile path at
Dockerfile and the Docker context at ., and click Update build strategy. While you’re on the Settings tab, copy the application’s ID: it’s the value of SEVALLA_APP_ID.4
Connect the database
Click the Networking tab. Under Connected services, click Add internal connection. Choose
orders-db as the Service, turn on Add environment variables to the application, and click Add internal connection. The template reads the DB_URL variable that Sevalla adds. See Connect an application.5
Create the bucket
In the sidebar, click Object storage, then click Create object storage. Enter a Name, choose the Location closest to the application, then click Create object storage. See Create a bucket.
6
Open the bucket to the admin panel
On the bucket’s Settings tab, under Public access, click Enable public access and confirm. Then, under CORS policy, click Create rule. Select
PUT, GET and HEAD under Allowed methods, enter the application’s address, such as https://storefront-x7k2m.sevalla.app, under Allowed origins and content-type under Allowed headers, then click Create CORS rule. See Bucket settings.7
Create an API key
In the sidebar, under Tools, click API keys, then click Create API key. Choose Custom capabilities and allow only updating this application (the
APP:UPDATE permission), then create the key and copy it. See API keys.8
Add the environment variables
On the application’s Environment variables tab, click Add environment variables. Add these variables and click Add environment variables:
The template reads them when the server starts, so they don’t need to be available during the build.
9
Turn on the CDN and edge caching
On the application’s Networking tab, under CDN & Edge caching, click Update settings. Turn on CDN and Edge caching, then click Done. See CDN and edge caching.
10
Deploy
Click the Overview tab, then click Deploy now under Recent deployments. Check the Branch and click Deploy.
11
Turn on auto-deploy
To deploy every push to the branch automatically, click the Settings tab, then click Update auto-deploy in the Auto-deploy section. Turn on Auto-deploy and click Update auto-deploy. See Deployments.
Verify the deployment
- On the Deployments tab, wait for the deployment’s status to change to Deployed. The application’s status next to its name changes to Running.
- Open the application’s address followed by
/_emdash/admin, for examplehttps://storefront-x7k2m.sevalla.app/_emdash/admin. The setup wizard creates the site, can load the demo content, and registers your admin passkey. EmDash applies its database migrations on the first request. - Publish a post, then open the site’s home page. The post shows without waiting for the cached page to expire, because publishing purges the edge cache.
DATABASE_URL is not set in the runtime logs, the internal connection didn’t add its variables: add the connection again with Add environment variables to the application turned on. If media uploads fail in the admin panel, check the bucket’s CORS rule.
Deploy changes
With Auto-deploy on, every push to the branch starts a deployment; otherwise, click Deploy now for each change. Each deployment builds the image, then replaces the web process’s instances. See Deployments.Add health checks
The template answers/healthz when the server runs and /healthz?db=1 when it can also reach PostgreSQL. Use them as the web process’s probes, so that Sevalla restarts an instance that stops responding and sends traffic only to instances that reach the database:
1
Open the web process
On the Processes tab, open the web process’s menu and click Update process.
2
Turn on the probes
Under Health checks, turn on Liveness probe with the Path
/healthz, and Readiness probe with the Path /healthz?db=1. Click Update process. The probes apply at the next deployment.Run migrations before each deployment
Without a job, the first request after a deployment applies EmDash’s pending migrations. To apply them once, before new instances get traffic, add a job:1
Create the job
On the Processes tab, click Create process and choose Job.
2
Set its command
Enter
Migrate as the Name and npm run migrate as the Custom start command. Keep the Start policy at Before deployment, then click Create process.migrate script runs emdash migrate without prompts. If the job fails, the deployment fails and nothing changes for visitors.
Add a custom domain
Custom domains need a web process larger than H1, so scale the web process first. After you add the domain on the Domains tab (see Custom domains):- Change
EMDASH_SITE_URLto the new address and deploy again. - Add the new address to the bucket’s CORS rule. Rules can’t be updated: delete the rule and create a new one with both origins.
- Register a passkey on the new domain before you remove the old one. Passkeys registered on the old address don’t work on the new one.