Quickstart (15 Minutes)
The main goal of RailsFast is getting you to put something online as fast as humanly possible.
I've worked really hard to make something that takes, literally, only 15 minutes to production.
While it won't be your finished product just yet, it will be something that at least is out there and people can visit. Something that proves your entire RailsFast workflow from development to production works fine. Something to build upon so you can start charging money as soon as possible.
This guide assumes you've already installed everything described in the Prerequisites section. Please make sure everything is installed and configured before continuing.
You can visit the demo project deployed in the video above live at demo.railsfast.com.
Kick off your RailsFast project
Start by accessing the main RailsFast repository railsfast/railsfast-base, to which you should have gotten access upon purchasing, and clone it:
git clone --origin railsfast https://github.com/railsfast/railsfast-base.git myapp
Replace myapp in the command above with the name of your app.
Open the myapp folder that has been created in Cursor. This is your very own RailsFast project now!
Push your project to GitHub
Right now you already have a working codebase, so let's save it to GitHub.
Open up your GitHub account and create a PRIVATE, empty repository (no template, no README, no .gitignore, no license).
Make sure the repository you create is private! RailsFast doesn't allow public repositories.
Point your local projectβs origin to your new repo:
git remote add origin https://github.com/YOUR-USERNAME/myapp.git
And push the code:
git branch -M main
git push -u origin main
Run the project setup script
Now open up your project in Cursor and run this in the terminal:
bin/railsfast init
This will start the interactive RailsFast setup script.
First, it will ask you to name your project. Then, it'll generate secure encryption files, build your encrypted credentials (with a fresh secret_key_base and Active Record encryption keys), set up the right deployment config, and essentially get your project ready for deployment.
Scripting the setup (or letting an AI agent run it)? The whole thing works non-interactively too: bin/railsfast init --yes --name "My App" skips every prompt. The name is kept exactly as you type it for all human-facing surfaces, while the derived module and database names are computed from it.
At the end, if everything went right, you should see a success message telling you the project is now ready to deploy.
Deploy your project
We're now ready to deploy the RailsFast project to production! We only need a server to deploy to.
A server may also be called a VPS (Virtual Private Server).
Spin up a server (VPS)
Go to Hetzner and log in to your dashboard.
Create a project if you don't have one (a "project" in Hetzner is just a named folder under which resources like servers are grouped).
Then, inside the Hetzner project, click on the [ Create Resource ] button, and then click on the [ Servers ] button.
Select a server type and size
For a low-traffic app (an app that's just starting, or a hobby project) pretty much any size will do. You can even fit multiple RailsFast apps in the same server to save costs.
For now, let's choose a good cheap-yet-powerful server with 2vCPUs and 2GB RAM:
- For type, choose:
Regular PerformanceunderShared Resources(x86) - For size, any 2 vCPU / 2β4 GB model does great. At the time of writing that's
cx23in Europe (~β¬5.49/mo) andcpx11in the US β but exact models, prices and stock genuinely shift week to week, so treat these as examples and check what's available where you deploy (next note).
A server like this will be more than enough and typically costs around β¬5/mo.
Hetzner's stock and pricing shift over time and vary per location β some days the cheapest machines are only in stock in one or two locations, and the same model can cost different amounts in different regions. Don't take the model names above as gospel: check what's actually available in your location before creating the server (any 2vCPU / 2GB+ shared x86 machine works great). In the terminal: hcloud server-type list shows every model with its specs and the locations where it's offered, and hcloud server-type describe cx23 shows, for each location, whether it's actually in stock (Available: yes/no) and its monthly price.
Agents, two specifics: parse with -o json (the human-readable output prints prices like β¬ 5.4900000000β¦, which naive text-splitting mangles into 0.00), and here's the cheapest-in-stock sweep in one go:
for t in cx23 cx33 cpx11 cpx21 cpx22; do
hcloud server-type describe $t -o json | jq -r '. as $st | $st.locations[]
| select(.available) | .name as $l
| ($st.prices[] | select(.location==$l)) as $p
| [$st.name, $l, $p.price_monthly.gross] | @tsv'
done | sort -t$'\t' -k3 -n | head -5
There are other cost-optimized options for about $3/mo you can experiment with, but their location availability may vary.
You can also choose a server a bit more expensive like CPX31 or CPX32 (4vCPUs and 8GB RAM) for ~$20/mo if you expect your app to have more traffic / load, if you expect to fit multiple apps in the same server, or if you'd just like to have some extra room to grow from the start.
Select a server location
Make sure to choose a location physically close to your customers (if your users are mainly in America, spin up the server in the US; if most of them are in Europe, choose one of the European locations, etc.)
Keep the rest of the config as default (Ubuntu OS image, public IPv4 and IPv6 addresses, etc.) β the RailsFast setup script supports both Ubuntu 24.04 LTS and 26.04 LTS, so whichever of those Hetzner offers as default works. Scroll down until the SSH section.
Create or choose a SSH key to access your server
To access your server and deploy code to it you'll need an SSH key. Create one if you don't have one:
ssh-keygen -t ed25519 -f ~/.ssh/my_hetzner_ssh_key
Replace my_hetzner_ssh_key with the name you want to give your SSH key.
Add your SSH key to your SSH agent so your terminal can actually connect to the server in the next steps:
ssh-add ~/.ssh/my_hetzner_ssh_key
Then display and copy your public key:
cat ~/.ssh/my_hetzner_ssh_key.pub
And paste the contents into the "Add an SSH key" box in Hetzner. Give it an identifiable name, like my_hetzner_ssh_key or whatever you named it in the previous step.
Add backups to your server
Now, optionally, you may want to add backups to your Hetzner server. It's just a checkbox: if you check it, Hetzner will make a daily copy of your server so you can easily recover things in case things go wrong. RailsFast already offers a different database backup mechanism, but it's always a good idea to have contingency plans in case, so if you're a bit paranoid like me just check it and Hetzner will have your back in case things go really wrong.
Run the initial server setup
To finish setting up our server, let's run the RailsFast setup script to harden the security of the server and install dependencies. It's all streamlined, you just need to paste this into the "Cloud Config" text box:
#cloud-config
runcmd:
- bash -lc 'set -euo pipefail; wget -qO /root/railsfast-setup.sh https://setup.railsfast.com; chmod +x /root/railsfast-setup.sh; /root/railsfast-setup.sh 2>&1 | tee -a /var/log/railsfast-setup.log && reboot'
This will use Cloud-init to run the RailsFast server setup script upon creation, and get the server ready to deploy apps to.
This Cloud-init snippet runs the server setup script you can find at setup.railsfast.com. If you prefer, you can do the initial setup manually to check the contents of the script. First, ssh into your server after it's created, then wget the setup script at setup.railsfast.com, inspect it, chmod +x it, and then execute it as root.
The setup script installs Docker from Docker's official repository, creates the key-only docker deploy user Kamal connects as, hardens SSH and the kernel, configures the firewall, fail2ban, and automatic security updates, adds swap on small servers, and verifies everything at the end. It's idempotent (safe to re-run β that's also how you upgrade servers set up with older versions of the script). For everything it does, its optional knobs, and how to maintain your server afterwards, see the server setup script guide.
You can explore the remaining server configuration options or just leave them as-is.
Finish the process by giving a name to your server (like "railsfast-production" or something that helps you keep things organized), and then click the [ Create & Buy Now ] button. Your server will now start being created and initialized.
Terminal / agent lane: the whole server creation is one hcloud CLI command. Save the Cloud Config snippet above as cloud-config.yml (anywhere β next to your project is fine), then:
hcloud ssh-key create --name my_hetzner_ssh_key --public-key-from-file ~/.ssh/my_hetzner_ssh_key.pub
hcloud server create --name railsfast-production --type cpx22 --location hel1 --image ubuntu-24.04 \
--ssh-key my_hetzner_ssh_key --user-data-from-file cloud-config.yml
The command prints the server's IP β that's the IP you'll use for DNS and deploy.yml below.
Authenticating hcloud: generating the API token is the one human step (Hetzner Console β your project β Security β API tokens β Generate, with Read & Write). Interactive humans run hcloud context create railsfast and paste it. For agents, the non-interactive pattern: the human saves the token to a chmod 600 file (e.g. ~/.config/railsfast/hcloud_token β see the secret handoff pattern), and every command reads it inline: HCLOUD_TOKEN="$(cat ~/.config/railsfast/hcloud_token)" hcloud server-type list β the token never touches the shell history or the chat transcript.
Optionally (recommended), add Hetzner's Cloud Firewall as an outer layer in two more commands β see the firewall truth:
hcloud firewall create --name railsfast-web --rules-file /dev/stdin <<'EOF'
[
{"direction":"in","protocol":"tcp","port":"22","source_ips":["0.0.0.0/0","::/0"]},
{"direction":"in","protocol":"tcp","port":"80","source_ips":["0.0.0.0/0","::/0"]},
{"direction":"in","protocol":"tcp","port":"443","source_ips":["0.0.0.0/0","::/0"]}
]
EOF
hcloud firewall apply-to-resource railsfast-web --type server --server railsfast-production
Wait for the server to initialize
We now need to wait for the server to boot up and the setup to complete (usually ~5 minutes)
You can check the status of the initialization Cloud-init setup by sshing as root into your server and running:
tail -f /var/log/cloud-init-output.log
Wait until you see a success message like π½ SUCCESS: Setup complete! and the system restarts. If you go and see the logs again after restarting, you'll now see cloud-init confirmation: Cloud-init... finished at...
If the success message never appears, the setup found a real problem and stopped (the server won't reboot in that case) β scroll up in that same log to see exactly which check failed. The script is safe to re-run after fixing it.
Terminal / agent lane: no need to watch logs β there's a machine-checkable readiness probe. The setup script writes /etc/railsfast-setup.version only after every verification passes, and the one thing Kamal needs is the docker user talking to Docker. So poll for both, as the docker user:
until ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new \
-i ~/.ssh/my_hetzner_ssh_key docker@YOUR_SERVER_IP \
'test -f /etc/railsfast-setup.version && docker info > /dev/null' 2>/dev/null
do sleep 20; done; echo "β
server ready to deploy"
A fresh server typically turns ready in ~4β6 minutes. One timing subtlety: the probe can pass in the brief window between setup finishing and the final reboot firing β then SSH drops for a few minutes while the server restarts. Require two or three consecutive passes (a few seconds apart) before you actually deploy, and treat one Connection refused right after a pass as the reboot, not a failure.
If it's still not ready after ~10 minutes, read /var/log/cloud-init-output.log on the server β the failed check will be right there. (Use your provider's web console for that if needed: after hardening, root SSH is key-only, and password login is off.)
You can keep going with the next quickstart steps while you wait, just make sure your server is all ready before you actually deploy!
Configure things for deployment
Let's get ready to actually deploy your RailsFast project to your server!
Point your domain's DNS to the server
First, go to wherever you manage your domain's DNS, and point your domain to the server's public IP address you can find in Hetzner.
For me, since I'm using Cloudflare to register and manage my domains, I navigate to my Domain, click on DNS > Records, and click the [ + Add record ] button to add a new record. Make the record of type A where the name is @ (root) and the IP address is the server's IPv4 address from Hetzner. Leave the proxy status active (Proxied).
If you also want www.myproject.com to work (recommended β people type it!), add a second record for it: another A record with name www pointing at the same IP (or a CNAME from www to @), Proxied too. You'll then list both hosts in deploy.yml in the next step.
Terminal / agent lane: Cloudflare DNS is two curl calls with a scoped API token. The one human step is creating the token (dash.cloudflare.com/profile/api-tokens β Create Token β "Edit zone DNS" template, scoped to just your zone; add Zone β Zone Settings β Read to the token if you also want to verify the SSL mode in the next step). Hand it to the agent via the secret handoff pattern, then:
CF_TOKEN="$(cat ~/.config/railsfast/cloudflare_token)"
# Find your zone ID:
ZONE_ID=$(curl -s -H "Authorization: Bearer $CF_TOKEN" \
"https://api.cloudflare.com/client/v4/zones?name=myproject.com" | jq -r '.result[0].id')
# Create the A record (name "@" for the root domain, or a subdomain name like "app"):
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
--data '{"type":"A","name":"@","content":"YOUR_SERVER_IP","proxied":true,"ttl":1}'
("ttl":1 means "automatic" β the right value for proxied records.)
Select the right SSL encryption mode
Then, still in Cloudflare, go to SSL/TLS > Overview and click on the [ Configure ] button. Select Full (Strict) encryption mode and click Save.
Terminal / agent lane: read the current mode first β the SSL mode is a zone-wide setting, so if the domain already serves other sites (e.g. you're deploying to a subdomain), changing it affects all of them. Agents: check, report, and only change it with the human's blessing if it's not already full or strict.
# Read (needs Zone β Zone Settings β Read on the token):
curl -s -H "Authorization: Bearer $CF_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ssl" | jq -r '.result.value'
# Set to Full (Strict) (needs Zone β Zone Settings β Edit):
curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ssl" \
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
--data '{"value":"strict"}'
If you don't do set the right SSL mode in Cloudflare, even if your deployment succeeds, your server will complain about weird redirect errors like this: "The page isnβt redirecting properly. Firefox has detected that the server is redirecting the request for this address in a way that will never complete. This problem can sometimes be caused by disabling or refusing to accept cookies."
Edit deploy.yml to let Rails know where to deploy to
After the A DNS record is set and the Full SSL encryption mode is set, go back to your RailsFast project in Cursor and edit the deploy.yml file you can find at config/deploy.yml.
The deploy.yml is where we'll add all the details about your server and domain name so the app actually knows where to deploy to.
Change the following things:
- IP: Replace the placeholder IP of your server. The placeholder IP is
1.2.3.4: search and replace, or replace manually in:servers>webaccessories>postgres>hostaccessories>pg-backup>host
- Domain: Replace the placeholder domain for your actual domain name in:
proxy>host- If you added a
wwwDNS record, serve both hosts by swapping the singlehost:key for ahosts:list:proxy: ssl: true hosts: - myproject.com - www.myproject.com forward_headers: true
- SSH: Replace the placeholder SSH key path for the actual path of your Hetzner SSH private key in (example:
~/.ssh/my_hetzner_ssh_key):ssh>keys
Now, optionally (but recommended):
- Configure a remote builder machine (if you're using macOS, you may have to do this)
- Configure a remote container registry
RailsFast uses Kamal for deployments. If you want to understand more about the deploy.yml file and what you can do re: deployments, check out the Kamal docs
If you add custom Kamal accessories (Redis, Elasticsearch, etc.) beyond the ones included in the RailsFast template, make sure to bind their ports to 127.0.0.1 β e.g. port: "127.0.0.1:9200:9200" instead of just port: "9200:9200". By default, Docker published ports bypass ufw rules, which means your accessory could be exposed to the internet even though the firewall is active. The default RailsFast accessories are already configured safely, this only applies to new accessories you may add.
Hit the deploy button
We're ready to deploy! Let's boot up the database and its scheduled backups:
bin/kamal accessory boot all
If you're not using a container registry, launch the Docker Desktop app (to run Docker engine).
Then, run this to set up and boot the local registry (and confirm your container registry credentials are okay if you're not using a local registry):
bin/kamal registry setup
If registry setup hangs for minutes with no output, it's almost always local Docker Desktop in a wedged state (telltale sign: docker ps responds instantly but docker start hangs on anything). Restart Docker Desktop, remove the half-created container if one exists (docker rm -f kamal-docker-registry), and re-run.
And then, finally, deploy your project with:
bin/kamal deploy
β Success! This gets your RailsFast app live. Visit your domain name on a web browser and you'll see the live demo page.
This is a good time to share your project online! If you use X (formerly Twitter), please post about it and tag me so I can see it!
π That's it! Your project is now running and living on the internet for about $5/mo, ready for full production usage, fully secured, on your own VPS that you fully control, where you own all your code and users' data, with no surprise $10k Vercel monthly bills! Welcome to freedom!
What you just got
I think it's worth repeating and making explicit everything you already have up and running now, because it's remarkable. Other templates require you several external dependencies, subscriptions to different services, and configuration headaches for something we've achieved here in under 15 minutes.
You now own:
- β A full-stack web application (not just a frontend decoy: both front and back-end) fully ready for production traffic
- β Running on your own domain
- β Secured with a SSL certificate (automatically issued on deployment and auto-renewed before expiration) which makes all client-server communications secure and strictly encrypted
- β A fully secure, production-ready database, DB schema, and migrations; all this with no external dependencies: you own all your user's data, nothing leaves your server, nobody can nuke your business by banning your Supabase account (because you don't need one!)
- β User authentication / login working by default, without any external dependencies either
- β Billing + payments: everything ready to start charging real money as soon as you configure your Stripe credentials in the next sections
- β You're running your entire business on your own server for a flat fee of less than $10/mo, without having to worry about getting traffic spikes (unlike Vercel!)
- β You can even fit multiple RailsFast projects in the same server, without having to pay more!
- β Your project is now ready to support thousands of users, right out of the box
- β Easily scalable to millions of users as your app grows (and even then, you won't be paying a fortune because servers are cheap!)
- β Plus all the features you can find in the features section of the docs, ready to go!
This quickstart may feel like a lot of steps, but it's only a one-time setup! Moving on, every time you want to deploy your app, you just need to run bin/kamal deploy
You're now ready to start developing (or vibe coding) your app! Your next step is customizing the base project to start making your app actually look like your own app.