Running on AWS
CHIPS runs on one Amazon EC2 instance. The Linux installer puts the Apache web server in front of it:
Apache answers on ports 80 and 443, and passes pages and live updates (WebSockets) to CHIPS, which
listens on 127.0.0.1:8080 only. PostgreSQL runs on the same instance, or in Amazon RDS.
┌──────────────────────────── VPC ───────────────────────────────┐
browser ─https─▶ Application Load Balancer ─http:80─▶ EC2: Apache ─▶ CHIPS ─▶ PostgreSQL
(ACM certificate, /healthz) (127.0.0.1:8080) (on the instance or RDS)
└────────────────────────────────────────────────────────────────┘
Choose one of three ways to give people an address:
| Mode | HTTPS | Use it when |
|---|---|---|
| alb (recommended) | An Application Load Balancer ends HTTPS with an AWS Certificate Manager (ACM) certificate and forwards to Apache on port 80 | Production; certificates renew by themselves; the instance can sit in a private subnet |
| letsencrypt | Apache on the instance, with a free Let's Encrypt certificate that renews automatically; an Elastic IP keeps the address | One instance, no load balancer cost |
| http | None | A short trial only: passwords travel unencrypted |
Quickest: the CloudFormation template
deploy/aws/chips-ec2.yaml (in the Linux package) creates everything: the instance (Amazon Linux 2023 by
default, IMDSv2 only, encrypted disk), its security groups, an IAM role (read the package from S3, Session
Manager instead of SSH), the load balancer with its target group and listeners or an Elastic IP, and
optionally the Route 53 record and an AWS Secrets Manager secret for an RDS database address.
- Upload the Linux package to an S3 bucket in the same account, e.g.
aws s3 cp chips-2.2.0-linux-x86_64.tar.gz s3://my-bucket/chips/(for Graviton instances also upload…-linux-aarch64.tar.gz; the template picks the one that matches). - For alb: request a certificate for your domain in ACM (in the region of the stack) and validate it.
- Create the stack:
aws cloudformation deploy --stack-name chips --template-file deploy/aws/chips-ec2.yaml \
--capabilities CAPABILITY_IAM --parameter-overrides \
PackageBucket=my-bucket Mode=alb DomainName=chips.example.com \
CertificateArn=arn:aws:acm:eu-west-1:123456789012:certificate/… \
HostedZoneId=Z0123456789ABC VpcId=vpc-… InstanceSubnet=subnet-… \
LoadBalancerSubnets=subnet-…,subnet-…
Without HostedZoneId, point your domain at the stack output DnsRecordToCreate yourself.
4. The install takes 3–6 minutes after the instance starts. The stack output SetupCode shows how to read
the one-time setup code through Session Manager. Then open the Address output, choose Set up CHIPS
and enter the code.
| Parameter | Meaning |
|---|---|
PackageBucket, PackageKey |
Where the package is; {arch} in the key becomes x86_64 or aarch64 |
Mode |
alb, letsencrypt or http (see above) |
DomainName |
The name people use (needed for alb and letsencrypt) |
CertificateArn |
ACM certificate for the name (alb) |
LetsEncryptEmail |
Address for certificate expiry notices (letsencrypt) |
HostedZoneId |
Optional Route 53 zone: the stack then creates the DNS record |
AllowedCidr |
Who may open CHIPS (default everyone, 0.0.0.0/0); narrow it to an office or VPN range |
VpcId, InstanceSubnet, LoadBalancerSubnets |
Network. The instance needs internet access to install packages (public subnet, or private with a NAT gateway in alb mode); the load balancer needs two public subnets in different zones |
InstanceType, ImageId, RootDeviceName, VolumeSize |
t3.small with Amazon Linux 2023 by default. Graviton: t4g.small and the arm64 image. Ubuntu 24.04: its image parameter and /dev/sda1 |
DatabaseUrl |
Optional Amazon RDS address (stored in Secrets Manager); empty = PostgreSQL on the instance |
Launching an instance by hand
- Launch an instance: Amazon Linux 2023, Ubuntu 22.04/24.04 or Debian 12, x86_64 or ARM64,
t3.smallor larger, 20 GB disk, IMDSv2 required is fine. - Security group: inbound TCP 80 and 443 from the people who use CHIPS (for
letsencrypt, port 80 from anywhere, because Let's Encrypt checks from the internet). Do not open 8080. For administration use Session Manager, or SSH from your own address only. - Optional: in Advanced details → User data, paste
deploy/aws/user-data.shafter filling in its settings at the top; it installs CHIPS at first start and logs to/var/log/chips-install.log. Otherwise copy the package to the instance and run the installer:
tar xzf chips-2.2.0-linux-x86_64.tar.gz && cd chips-2.2.0
sudo ./deploy/install.sh # http
sudo ./deploy/install.sh --domain chips.example.com --letsencrypt you@example.com # letsencrypt
sudo ./deploy/install.sh --domain chips.example.com --alb # alb
letsencrypt: allocate an Elastic IP, associate it with the instance and point the domain's A record at it before running the installer. Without a domain (http), the address is the instance's public DNS name, which changes when the instance is stopped; an Elastic IP keeps it.alb: create a target group (type instance, protocol HTTP, port 80, health check path/healthz, success code 200), register the instance, and an Application Load Balancer with an HTTPS listener on 443 (ACM certificate, forward to the target group) and an HTTP listener on 80 that redirects to HTTPS. Allow port 80 on the instance from the load balancer's security group only.
Change the mode later at any time, without reinstalling:
sudo /opt/scrum-poker/deploy/apache.sh --domain chips.example.com --alb (see
Apache web server and AWS).
What the installer sets up for AWS
- CHIPS listens on
127.0.0.1:8080; only Apache (ports 80/443) is reachable. - The address (
PUBLIC_URL) is your domain, or the instance's public DNS name read from the instance metadata (IMDSv2). - alb: Apache accepts requests only from the VPC's address ranges (read from the instance metadata, or
--trusted-proxies), and CHIPS trusts the load balancer'sX-Forwarded-ForandX-Forwarded-Protoheaders from those ranges only (FORWARDED_ALLOW_IPS). So CHIPS sees each visitor's real address (for the activity log and for blocking password guessing) and knows the visit was over HTTPS (secure cookies, HSTS). Apache's access log records the visitor's address too. - letsencrypt: HTTP redirects to HTTPS, TLS 1.2 and 1.3 only;
certbotrenews the certificate and reloads Apache. - WebSockets work through Apache and the load balancer with no extra settings. The live connection exchanges a short message every few seconds, well inside the load balancer's idle timeout (60 seconds by default; the template sets 120).
- SELinux (if enforcing) is allowed to let Apache connect to CHIPS; firewalld or ufw, when active, are opened for 80/443.
Amazon RDS for PostgreSQL
- Create an RDS for PostgreSQL database (version 13 or later; 16 recommended) in the same VPC, with a
database and a user for CHIPS, e.g.
chips. - Allow TCP 5432 into the database's security group from the instance's security group.
- Install with its address (RDS requires TLS, hence
sslmode=require):
sudo ./deploy/install.sh --domain chips.example.com --alb \
--database-url 'postgresql://chips:PASSWORD@chips.xxxx.eu-west-1.rds.amazonaws.com:5432/chips?sslmode=require'
The installer checks the connection first, then installs no PostgreSQL server on the instance. CHIPS creates its tables at start-up. Uninstalling never deletes an RDS database. Backups are RDS's automated backups and snapshots.
Operating it
| Task | How |
|---|---|
| Health check / monitoring | GET /healthz → 200, or 503 when the database does not answer. A CloudWatch alarm on the target group's UnHealthyHostCount covers it |
| Logs | journalctl -u scrum-poker; Apache: /var/log/httpd/chips-*.log (Amazon Linux) or /var/log/apache2/chips-*.log (Ubuntu/Debian). The CloudWatch agent can ship them |
| Backups | PostgreSQL on the instance: EBS snapshots with Amazon Data Lifecycle Manager, plus pg_dump (see Backups and restore); RDS: automated backups |
| Upgrades | Copy the new package to the instance and run sudo ./deploy/install.sh again; the database and settings are kept |
| Scaling | Run one instance: live updates are delivered within the process. Choose a larger instance type for more rooms at once |
| Remove | sudo /opt/scrum-poker/deploy/uninstall.sh, or delete the CloudFormation stack |