Step 1 — Launch an EC2 instance
- Go to EC2 Console (opens in a new tab) → Instances → Launch instances
- Fill in the form:
| Field | Recommended value |
|---|---|
| Name | rtsurvey-prod |
| AMI | Ubuntu Server 22.04 LTS (HVM) |
| Instance type | t3.medium (2 vCPU / 4 GB RAM) |
| Key pair | Select or create a key pair for SSH access |
| Security group | Create new — see Security group rules below |
- Expand Advanced details → scroll to User data
- Choose how to deploy:
Option A — Bootstrap snippet (EC2 console, recommended)
AWS user-data has a 16 KB paste limit. The full script exceeds this, so paste this small bootstrap instead — it fetches the full script from GitHub at first boot:
#!/bin/bash
export PROJECT_ID="rtsurvey"
export ADMIN_PASSWORD="admin"
export EMBED_KEYCLOAK="true"
export TZ="Asia/Ho_Chi_Minh"
curl -fsSL https://raw.githubusercontent.com/therealtimex/rtsurvey/main/scripts/aws-ec2.sh | bashCustomise by changing the export lines before launching.
Option B — Full script via AWS CLI
The 16 KB limit does not apply when uploading via the CLI. Download aws-ec2.sh, edit the CONFIGURATION block at the top, then launch:
aws ec2 run-instances \
--image-id ami-0c02fb55956c7d316 \
--instance-type t3.medium \
--key-name YOUR_KEY_PAIR \
--security-group-ids sg-xxxxxxxx \
--user-data file://aws-ec2.sh \
--count 1- Click Launch instance (Option A) or run the CLI command (Option B)
Recommended instance types
| Instance type | RAM | ~$/month | Notes |
|---|---|---|---|
t3.medium | 4 GB | ~$30 | Minimum for Keycloak |
t3.large | 8 GB | ~$60 | Recommended for production |
Step 2 — Configure security group rules
Create a new security group with these inbound rules:
| Type | Protocol | Port | Source | Notes |
|---|---|---|---|---|
| SSH | TCP | 22 | Your IP | Admin access |
| HTTP | TCP | 80 | 0.0.0.0/0 | Nginx + ACME challenge |
| HTTPS | TCP | 443 | 0.0.0.0/0 | Nginx after SSL setup |
| Custom TCP | TCP | 3838 | 0.0.0.0/0 | Shiny Server (R analytics) |
Outbound: Allow all (required for Docker image pulls and Let's Encrypt).
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. Open your browser and go to http://<instance-public-ip>. You will see a loading page while the app finishes starting up. It refreshes automatically every 5 seconds and loads the app once ready.
The instance public IP is shown in the EC2 → Instances list. If you assigned an Elastic IP, use that instead.
To watch the log directly:
ssh ubuntu@<instance-public-ip>
sudo tail -f /var/log/rtsurvey-setup.logStep 4 — Set up SSL
Once 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)
Security group rules
Inbound
| Type | Protocol | Port | Source | Notes |
|---|---|---|---|---|
| SSH | TCP | 22 | Your IP | SSH access |
| HTTP | TCP | 80 | 0.0.0.0/0 | Nginx HTTP + ACME challenge |
| HTTPS | TCP | 443 | 0.0.0.0/0 | Nginx HTTPS after SSL setup |
| Custom TCP | TCP | 3838 | 0.0.0.0/0 | Shiny Server (R analytics) |
Outbound
| Type | Protocol | Port | Destination | Notes |
|---|---|---|---|---|
| All traffic | All | All | 0.0.0.0/0 | Docker pulls, certbot, etc. |
Ports NOT needed externally
| 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
sudo tail -200 /var/log/rtsurvey-setup.logCheck the SSL log
sudo tail -200 /var/log/rtsurvey-ssl.logView container status
docker compose -f /opt/rtsurvey/docker-compose.production.yml ps