Make sure to start a Postgres DB locally (docker compose up). Then create a .env file with a DATABASE_URL for prisma. You can look at the example provided in .env.example.
bun install
bunx prisma migrate dev # Will apply db migrations
bunx prisma generate
bun run devTo create a production version of your app:
bun run buildYou can preview the production build with npm run preview.
Start an EC2 instance on AWS. Recommended settings:
- Distribution: Debian 12
- Architecture: 64-bit Arm (needed to use
t4g.*instances) - Instance type: t4g.small
- Network settings: Open ports for SSH and HTTP/HTTPS.
- Storage: default settings (8 GiB gp3)
SSH into the instance and run the following commands:
sudo apt update
sudo apt upgradeWe will use a GitHub self-hosted runner to execute some workflows directly on our server. To configure a self-hosted runner, go to your repo's setting > Actions > Runners then follow the guide.
cd ~/actions-runner
sudo ./svc.sh install
sudo ./svc.sh start
# To check status
sudo ./svc.sh statusFirst, we'll configure the server to use fr_CA locale and America/Montreal timezone.
sudo localedef -i fr_CA -c -f UTF-8 -A /usr/share/locale/locale.alias fr_CA.UTF-8
sudo update-locale LANG=fr_CA.UTF-8
export LANG=fr_CA.UTF-8
sudo timedatectl set-timezone America/MontrealThen, install Postgres:
sudo apt install postgresqlsudo -u postgres psql <<EOF
CREATE USER [USERNAME] WITH PASSWORD '[PASSWORD]';
ALTER USER [USERNAME] CREATEDB;
EOF
sudo -u postgres createdb [DB_NAME] -O [USERNAME]Run the following command to connect to the database and make sure everything is working:
psql -U [USERNAME] -d postgres -h localhost -d [DB_NAME] -Wpg_dump -U [USERNAME] -h localhost -d [DB_NAME] -F c -f ~/db_backups/[DB_NAME].[DATE].backupTo restore the db on a new server/db:
# Create a new DB
sudo -u postgres createdb [DB_NAME] -O [USERNAME]
# Restore
pg_restore -U [USERNAME] -d [DB_NAME] ~/db_backups/[DB_NAME].[DATE].backupOr if you want pg_restore to create the database automatically:
pg_restore -U [USERNAME] -C ~/db_backups/[DB_NAME].[DATE].backupYou can export a backup from the server to your local computer:
scp -i /path/to/your/key.pem [LINUX_USER]@[PUBLIC_IP]:~/db_backups/[DB_NAME].[DATE].backup ~/Downloads/You can push a local backup to the server:
scp -i /path/to/your/key.pem ~/[DB_NAE].[DATE].backup [LINUX_USER]@[EC2_PUBLIC_IP]:~/db_backups/We are using Bun to bundle the project. We can install bun using:
sudo apt install unzip # Needed to install bun
curl -fsSL https://bun.sh/install | bash
sudo ln -s $HOME/.bun/bin/bun /usr/local/bin/bun
sudo ln -s $HOME/.bun/bin/bunx /usr/local/bin/bunx
source ~/.bashrcWe are using pm2 to run the website in the background. We can install pm2 using:
bun install --global pm2
bunx pm2 -v(Prerequisite: setup a domain that points to the ec2 instance)
We need Nginx to act as a reverse proxy to redirect all requests on 80/443 to 3000. We can install nginx using:
sudo apt install nginxIn /etc/nginx/nginx.conf, comment the following line: include /etc/nginx/sites-enabled/*;, then reload nginx with sudo nginx -s reload.
Create a new conf file for nginx.
vim /etc/nginx/conf.d/hub-sorel-tracy.confIn the newly created file, add the following server blocks:
server {
listen 80;
server_name hub-sorel-tracy.mathiscote.ca;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name hub-sorel-tracy.mathiscote.ca;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Pass real client info
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for SSE/WebSockets
proxy_buffering off;
# Augment buffer size to avoid nginx cutting down response, causing a 502 gateway error
proxy_buffers 16 16k;
proxy_buffer_size 32k;
}
}First, install certbot:
sudo apt install certbot python3-certbot-nginxThen, request a free certificate:
sudo certbot --nginx -d [DOMAIN]When Certbot is done generating the certificates, you can open the nginx config file:
vim /etc/nginx/conf.d/hub-sorel-tracy.confYou'll see that Certbot changed some stuff. Make sure the config file is like this (you'll need to delete some stuff and move stuff around):
server {
if ($host = hub-sorel-tracy.mathiscote.ca) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name hub-sorel-tracy.mathiscote.ca;
return 404; # managed by Certbot
}
server {
listen 443 ssl;
server_name hub-sorel-tracy.mathiscote.ca;
ssl_certificate /etc/letsencrypt/live/hub-sorel-tracy.mathiscote.ca/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/hub-sorel-tracy.mathiscote.ca/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Pass real client info
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for SSE/WebSockets
proxy_buffering off;
# Augment buffer size to avoid nginx cutting responses, causing 502 gateway error
proxy_buffers 16 16k;
proxy_buffer_size 32k;
}
}To renew the certificates:
sudo certbot renew