docs/ts/self-host/deploy-to-railway.md
If you prefer manual deployment over the automation offered by Encore's Platform, Encore simplifies the process of deploying your app to the cloud provider of your choice. This guide will walk you through deploying an Encore app to Railway using Docker through GitHub Actions.
Create a New Encore App:
encore app create
Hello World template.Push the code to a GitHub repo:
To deploy your Docker image to Railway, you first need to push it to a container registry. We will be using GitHub's container registry, but you can also use DockerHub or other registries. Instead of pushing the image manually we will be using GitHub actions to automate the process.
.github/workflows/deploy-image-yaml file with the following contents:name: Build, Push and Deploy a Docker Image to Railway
on:
push:
branches: [ main ]
permissions:
contents: read
packages: write
jobs:
build-push-deploy-image:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Download Encore CLI script
uses: sozo-design/[email protected]
with:
args: --output install.sh -L https://encore.dev/install.sh
- name: Install Encore CLI
run: bash install.sh
- name: Build Docker image
run: /home/runner/.encore/bin/encore build --config railway-infra.config.json docker myapp
- name: Tag Docker image
run: docker tag myapp ghcr.io/${{ github.repository }}:latest
- name: Push Docker image
run: docker push ghcr.io/${{ github.repository }}:latest
This will install the Encore CLI, build the Docker image, tag it, and push it to GitHub's container registry everytime you push to the main branch.
The dynamic values like ${{ github.repository }} will be filled in automatically by GitHub, you should not need to do anything.
Create a new Project on Railway:
Create a new service inside your new project:
ghcr.io/username/repo:latest. You can should be able to find the Docker Image under Packages in your GitHub repo.Expose the service:
8080 as the port.Access the application:
https://repo-name-production.up.railway.app/. curl https://repo-name-production.up.railway.app/hello/world
Railway has no way of knowing that you've pushed a new image to the container registry, but we can use Railway's GraphQL API to trigger a new deployment whenever a new image is pushed to the registry.
Generate a Railway API Token:
Add the Railway API Token to GitHub Secrets:
RAILWAY_API_TOKEN and paste the token you copied earlier.Add a JavaScript script to your repo:
script.js with the following contents:const TOKEN = process.argv.slice(2)[0];
const ENVIRONMENT_ID = "<your environment id>"
const SERVICE_ID = "<your service id>"
const resp = await fetch('https://backboard.railway.com/graphql/v2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'authorization': `Bearer ${TOKEN}`,
},
body: JSON.stringify({
query: `
mutation ServiceInstanceRedeploy {
serviceInstanceRedeploy(
environmentId: "${ENVIRONMENT_ID}"
serviceId: "${SERVICE_ID}"
)
}`
}),
})
const data = await resp.json()
if (data.errors) {
console.error(data.errors)
throw new Error('Failed to redeploy service')
}
console.log(data)
<your environment id> and <your service id> with the actual values. You can find these values in the Railway dashboard URL when you're on the service page. - name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Trigger Railway deployment
run: node script.js ${{ secrets.RAILWAY_API_TOKEN }}
Whenever you push a new Docker Image to the container registry, the GitHub action will trigger a new deployment on Railway.
Railway provides managed databases, allowing you to add a database to your app easily. Here’s how to set up a database for your app:
Create a database for your app on Railway:
Copy the connection details:
psql command connection details.Create a database table:
psql command:PGPASSWORD=<password> psql -h <hostname>.rlwy.net -U postgres -p 39684 -d railway
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
INSERT INTO users (name) VALUES ('Alice');
Declare a Database in your Encore app:
mydb database to your app (Encore Database Documentation) const mydb = new SQLDatabase("mydb", {
migrations: "./migrations",
});
export const getUser = api(
{ expose: true, method: "GET", path: "/names/:id" },
async ({id}: {id:number}): Promise<{ id: number; name: string }> => {
return await mydb.queryRow`SELECT * FROM users WHERE id = ${id}` as { id: number; name: string };
}
);
Create an Encore Infrastructure config
infra.config.json in the root of your Encore app.{
"$schema": "https://encore.dev/schemas/infra.schema.json",
"sql_servers": [
{
"host": "<hostname>.rlwy.net:39684",
"tls_config": {
"disable_ca_validation": true
},
"databases": {
"mydb": {
"name": "railway",
"username": "postgres",
"password": {"$env": "DB_PASSWORD"}
}
}
}]
}
Railway does not allow for downloading the CA certificate for the database, so we disable the CA validation.
Set Up Environment Variables (Optional):
DB_PASSWORD.Make a new deployment:
Test the Database Connection:
curl https://myapp.railway.app/names/1
That’s it! You’ve successfully deployed an Encore app to Railway using Docker. You can now scale your app, monitor its performance, and manage it easily through the Railway dashboard. If you encounter any issues, refer to the Railway documentation or the Encore community for help. Happy coding!