Step 1 — Launch the StackScript
Deploy rtSurvey on Linode → (opens in a new tab)
This opens the StackScript page in Linode Cloud Manager. Click Deploy New Linode.
Step 2 — Fill in Linode's form
Fill in Linode's standard server creation form:
| Field | Recommended value |
|---|---|
| Image | Ubuntu 22.04 LTS |
| Region | Closest to your users |
| Plan | Shared CPU 4 GB or larger |
| Root Password | Set a strong password |
| Firewall | No Firewall (recommended) |
| Timezone (our only field) | Your server timezone (default: Asia/Ho_Chi_Minh) |
Why no firewall? The setup script needs outbound internet access (Docker pulls, Let's Encrypt). Blocking ports during first boot can cause the deployment to fail. You can attach a firewall after setup is complete — see Firewall rules below for the correct rules.
Click Create Linode when done.
Step 3 — Wait for setup to complete
The script runs automatically on first boot. It installs Docker, pulls the rtSurvey image, initialises the database, and starts all services. This takes 5–10 minutes.
No console access needed. Just open your browser and navigate to your domain (or the server IP) after about 2–3 minutes. You will see a branded loading page while the app finishes starting up. The page refreshes automatically every 20 seconds. Once the app is fully started, it loads automatically — no manual refresh needed.
Tip: The server IP is shown in the Linode dashboard (opens in a new tab) on the Linode detail page. If DNS is already pointing to the server, you can use your domain name directly.
Step 4 — Set up SSL
Once the loading page disappears and the app is running, follow the Set Up SSL guide → to configure HTTPS. The free rtsurvey.com subdomain is the fastest option — no DNS setup needed.
Step 5 — Change the default password
All passwords default to admin. Change them immediately after your first login:
- App admin password — account settings inside the app
- Keycloak admin — accessible at
https://your-domain.com/auth/admin(login:admin/admin)
Firewall rules (Linode Cloud Firewall)
If you attach a Linode Cloud Firewall to this server, use the following rules:
Inbound
| Label | Action | Protocol | Port | Sources | Notes |
|---|---|---|---|---|---|
accept-inbound-ssh | Accept | TCP | 22 | All IPv4, All IPv6 | SSH access |
accept-inbound-http | Accept | TCP | 80 | All IPv4, All IPv6 | Nginx (HTTP + ACME challenge) |
accept-inbound-https | Accept | TCP | 443 | All IPv4, All IPv6 | Nginx (HTTPS after SSL setup) |
accept-inbound-shiny | Accept | TCP | 3838 | All IPv4, All IPv6 | Shiny Server (R analytics) |
accept-inbound-icmp | Accept | ICMP | — | All IPv4, All IPv6 | Ping / diagnostics |
| Default inbound policy | Drop | Block everything else |
Outbound
| Label | Action | Notes |
|---|---|---|
| Default outbound policy | Accept | Allow all outbound (Docker pulls, certbot, GoDaddy API, etc.) |
Ports NOT needed externally
These ports are bound to 127.0.0.1 only and never reachable from outside the server:
| Port | Service | Reason |
|---|---|---|
| 8080 | App container | Nginx proxies to it internally |
| 8090 | Keycloak container | Nginx proxies to it internally |
| 3306 | MySQL | Internal Docker network only |
Troubleshooting
Check the setup log
tail -200 /var/log/stackscript.logCheck the SSL log
tail -200 /var/log/rtsurvey-ssl.logView container status
docker compose -f /opt/rtsurvey/docker-compose.production.yml ps