Skip to content

Commit d0be354

Browse files
elifoutsCopilotCopilotgrillinr
authored
AWS-ready (#142)
* AWS-ready * Update backend/api/static/account-deletion.html Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix review comments: AASA content-type, proxy header spoofing, API_BASE_URL const mutation, installer guard, docs (#143) * Initial plan * Address PR review comments: AASA content-type, proxy header security, template check, API_BASE_URL fix, docs update Co-authored-by: elifouts <116454864+elifouts@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: elifouts <116454864+elifouts@users.noreply.github.com> * Consolidate static/compliance files to single source of truth with sync script (#144) * Initial plan * Add sync-static.sh to prevent static file drift; fix account-deletion.html email Co-authored-by: grillinr <169214325+grillinr@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: grillinr <169214325+grillinr@users.noreply.github.com> * Refactor scripts and components for improved clarity and functionality; update TypeScript configurations and enhance local development experience. * Update deployment instructions and scripts for AWS EC2 native setup; change default user to ec2-user and enhance clarity in documentation. * updated scripts for aws * updated instructions fr * screw this file * fixed --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: grillinr <169214325+grillinr@users.noreply.github.com>
1 parent 0a99b53 commit d0be354

67 files changed

Lines changed: 1658 additions & 1195 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
EXPO_PUBLIC_USE_LOCAL_API=1
22
EXPO_PUBLIC_LOCAL_API_URL=http://192.168.76.129:8080
3-
EXPO_PUBLIC_API_URL=https://devbits.ddns.net
3+
EXPO_PUBLIC_API_URL=https://devbits.app
44
EXPO_PUBLIC_LOCAL_API_PORT=8080
55
POSTGRES_DB=devbits_dev
66
POSTGRES_USER=devbits_dev
7-
POSTGRES_PASSWORD=devbits_dev_password
7+
POSTGRES_PASSWORD=devbits_dev_password

Bash-Scripts/run-dev.sh

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env bash
22

33
# Script: run-dev.sh
4-
# Does: Boots local dev DB + local backend (isolated compose project), then launches frontend in local mode.
5-
# Use: ./run-dev.sh [--clear]
4+
# Does: Boots local dev DB + local backend (isolated compose project) only.
5+
# Use: ./run-dev.sh
66
# DB: devbits_dev (user/pass: devbits_dev/devbits_dev_password) in compose project devbits-dev-local.
77
# Ports: backend default :8080, DB default :5433 (DEVBITS_BACKEND_PORT / DEVBITS_DB_PORT override).
8-
# Modes: Frontend=ON(local API) | Backend=ON(local Docker) | Live stack untouched | Test DB untouched.
8+
# Modes: Frontend=OFF | Backend=ON(local Docker) | Live stack untouched | Test DB untouched.
99

1010
set -euo pipefail
1111

@@ -14,9 +14,9 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
1414
BACKEND_DIR="$ROOT/backend"
1515
COMPOSE_PROJECT="devbits-dev-local"
1616

17-
CLEAR_FRONTEND=""
18-
if [[ "${1:-}" == "--clear" ]]; then
19-
CLEAR_FRONTEND="--clear"
17+
if [[ "${EUID}" -eq 0 ]]; then
18+
echo "Warning: Running as root is not recommended for Expo local mode."
19+
echo "Use ./run-dev.sh (without sudo) so LAN IP detection and device connectivity work reliably."
2020
fi
2121

2222
if ! command -v docker >/dev/null 2>&1; then
@@ -109,6 +109,10 @@ for i in $(seq 1 60); do
109109
sleep 1
110110
done
111111

112-
echo "Launching frontend in local backend mode..."
113-
cd "$ROOT"
114-
EXPO_PUBLIC_LOCAL_API_PORT="$DEVBITS_BACKEND_PORT" "$SCRIPT_DIR/run-front.sh" --local $CLEAR_FRONTEND
112+
echo
113+
echo "Local backend stack is ready."
114+
echo "Backend health: http://localhost:${DEVBITS_BACKEND_PORT}/health"
115+
echo "To launch frontend against local backend, run:"
116+
echo " EXPO_PUBLIC_LOCAL_API_PORT=${DEVBITS_BACKEND_PORT} $SCRIPT_DIR/run-front.sh --local"
117+
echo "To launch frontend against live backend, run:"
118+
echo " $SCRIPT_DIR/run-front.sh --live"

Bash-Scripts/run-front.sh

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env bash
22

33
# Script: run-front.sh
4-
# Does: Starts Expo frontend and lets you choose backend target (Production or Local).
5-
# Use: ./run-front.sh [--local|--production] [--clear] [--dev-client]
4+
# Does: Starts Expo frontend and lets you choose backend target (Local or Live).
5+
# Use: ./run-front.sh [--local|--live|--production] [--clear] [--dev-client]
66
# DB: None (frontend only).
77
# Ports: Metro uses LAN IP; local API defaults to :8080 (EXPO_PUBLIC_LOCAL_API_PORT overrides).
88
# Modes: Frontend=ON | Backend=Production URL or Local URL | Live stack untouched | Dev/Test DB untouched.
@@ -31,26 +31,53 @@ for arg in "$@"; do
3131
--production)
3232
MODE="production"
3333
;;
34+
--live)
35+
MODE="production"
36+
;;
3437
*)
3538
echo "Unknown argument: $arg"
36-
echo "Usage: ./run-front.sh [--local|--production] [--clear] [--dev-client]"
39+
echo "Usage: ./run-front.sh [--local|--live|--production] [--clear] [--dev-client]"
3740
exit 1
3841
;;
3942
esac
4043
done
4144

4245
detect_lan_ip() {
43-
hostname -I 2>/dev/null | tr ' ' '\n' | grep -E '^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.' | head -n1
46+
local from_route=""
47+
local iface=""
48+
49+
if command -v ip >/dev/null 2>&1; then
50+
from_route="$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1; i<=NF; i++) if ($i=="src") {print $(i+1); exit}}')"
51+
if [[ "$from_route" =~ ^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\. ]]; then
52+
echo "$from_route"
53+
return 0
54+
fi
55+
56+
iface="$(ip route 2>/dev/null | awk '/^default/ {print $5; exit}')"
57+
if [[ -n "$iface" ]]; then
58+
ip -4 addr show dev "$iface" scope global 2>/dev/null |
59+
awk '/inet / {print $2}' |
60+
cut -d/ -f1 |
61+
grep -E '^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.' |
62+
head -n1
63+
return 0
64+
fi
65+
fi
66+
67+
hostname -I 2>/dev/null |
68+
tr ' ' '\n' |
69+
grep -E '^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.' |
70+
head -n1
4471
}
4572

4673
LAN_IP="$(detect_lan_ip || true)"
4774
if [[ -z "$LAN_IP" ]]; then
4875
LAN_IP="127.0.0.1"
49-
echo "Warning: Could not detect private LAN IPv4. Falling back to 127.0.0.1."
76+
echo "Warning: Could not detect private LAN IPv4."
5077
fi
5178

5279
if [[ -z "$MODE" ]]; then
53-
echo "Select backend: 1) Production (devbits.ddns.net) 2) Local (LAN IP:8080)"
80+
echo "Select backend: 1) Live (devbits.app) 2) Local (LAN IP:8080)"
5481
read -r -p "Choose [1/2]: " selection
5582
case "$selection" in
5683
1) MODE="production" ;;
@@ -69,18 +96,30 @@ else
6996
unset REACT_NATIVE_PACKAGER_HOSTNAME || true
7097
unset EXPO_PACKAGER_HOSTNAME || true
7198
fi
72-
export EXPO_PUBLIC_API_URL="https://devbits.ddns.net"
73-
export EXPO_PUBLIC_API_FALLBACK_URL="https://devbits.ddns.net"
99+
export EXPO_PUBLIC_API_URL="https://devbits.app"
100+
export EXPO_PUBLIC_API_FALLBACK_URL="https://devbits.app"
74101

75102
if [[ "$MODE" == "local" ]]; then
76103
LOCAL_API_PORT="${EXPO_PUBLIC_LOCAL_API_PORT:-8080}"
104+
105+
if [[ "$LAN_IP" == "127.0.0.1" && "${DEVBITS_ALLOW_LOOPBACK_LOCAL_API:-0}" != "1" ]]; then
106+
echo "Error: Local mode resolved loopback (127.0.0.1), which will fail on physical devices."
107+
echo "Fix one of the following and try again:"
108+
echo " 1) Run without sudo so network detection can read your user network context."
109+
echo " 2) Set EXPO_PUBLIC_LOCAL_API_URL manually, e.g. http://192.168.x.y:${LOCAL_API_PORT}."
110+
echo " 3) If using only simulator/emulator intentionally, set DEVBITS_ALLOW_LOOPBACK_LOCAL_API=1."
111+
exit 1
112+
fi
113+
77114
export EXPO_PUBLIC_USE_LOCAL_API=1
78-
export EXPO_PUBLIC_LOCAL_API_URL="http://${LAN_IP}:${LOCAL_API_PORT}"
115+
if [[ -z "${EXPO_PUBLIC_LOCAL_API_URL:-}" ]]; then
116+
export EXPO_PUBLIC_LOCAL_API_URL="http://${LAN_IP}:${LOCAL_API_PORT}"
117+
fi
79118
echo "Using local backend: $EXPO_PUBLIC_LOCAL_API_URL"
80119
else
81120
export EXPO_PUBLIC_USE_LOCAL_API=0
82121
unset EXPO_PUBLIC_LOCAL_API_URL || true
83-
echo "Using production backend: https://devbits.ddns.net"
122+
echo "Using live backend: https://devbits.app"
84123
fi
85124

86125
cd "$FRONTEND_DIR"

Bash-Scripts/sync-static.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
# Script: sync-static.sh
3+
# Does: Copies compliance/static files from backend/api/static (source of truth) to frontend/public.
4+
# Run this whenever the backend static files change to keep the frontend web build in sync.
5+
# Use: ./sync-static.sh
6+
7+
set -euo pipefail
8+
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11+
12+
SRC="$ROOT/backend/api/static"
13+
DST="$ROOT/frontend/public"
14+
15+
FILES=(
16+
apple-app-site-association
17+
privacy-policy.html
18+
account-deletion.html
19+
)
20+
21+
for file in "${FILES[@]}"; do
22+
src_path="$SRC/$file"
23+
dst_path="$DST/$file"
24+
25+
if [[ ! -f "$src_path" ]]; then
26+
echo "WARNING: Source file not found, skipping: $src_path"
27+
continue
28+
fi
29+
30+
if cmp -s "$src_path" "$dst_path" 2>/dev/null; then
31+
echo "Up to date: $file"
32+
else
33+
cp "$src_path" "$dst_path"
34+
echo "Synced: $file"
35+
fi
36+
done
37+
38+
echo "Sync complete."

INSTRUCTIONS.md

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,50 @@
22

33
## Backend
44

5-
> **Live/Deployed Stack**
5+
> **AWS EC2 (Amazon Linux) Native Deploy**
66
>
77
> ```bash
8-
> cd /path/to/DevBits/backend
9-
> docker compose up -d
10-
> docker compose logs -f db
8+
> # On your EC2 instance
9+
> sudo dnf update -y
10+
> sudo dnf install -y git tar
1111
> ```
12-
13-
> Rebuild and restart:
12+
>
13+
> Install Go 1.24.x (required by `backend/go.mod`):
1414
>
1515
> ```bash
16-
> docker compose up -d --build
16+
> curl -LO https://go.dev/dl/go1.24.2.linux-amd64.tar.gz
17+
> sudo rm -rf /usr/local/go
18+
> sudo tar -C /usr/local -xzf go1.24.2.linux-amd64.tar.gz
19+
> echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
20+
> source ~/.bashrc
21+
> go version
1722
> ```
18-
23+
>
24+
> Clone and deploy:
25+
>
26+
> ```bash
27+
> sudo mkdir -p /opt/devbits
28+
> sudo chown -R "$USER":"$USER" /opt/devbits
29+
> cd /opt/devbits
30+
> git clone https://github.com/devbits-go/DevBits.git .
31+
> git checkout aws-ready-main
32+
> cd backend
33+
> cp .env.example .env
34+
> # edit .env with production values (DATABASE_URL, secrets, CORS, etc.)
35+
> ./scripts/deploy-aws-native.sh
36+
> ```
37+
>
38+
> Verify service:
39+
>
40+
> ```bash
41+
> sudo systemctl status devbits-api --no-pager
42+
> sudo journalctl -u devbits-api -n 120 --no-pager
43+
> curl -i http://127.0.0.1:8080/health
44+
> ```
45+
>
1946
> [!TIP]
20-
> Check `backend/scripts/README.md` for database operations.
47+
> AWS deploy uses native `systemd` (no Docker or nginx required in production).
48+
> See `backend/docs/AWS_TRANSFER_NO_NGINX.md` for full runbook.
2149
2250
## Build
2351
@@ -58,4 +86,4 @@
5886
5987
---
6088
61-
`Workflow: Backend Setup → EAS Build → EAS Submit`
89+
`Workflow: AWS Backend Deploy → EAS Build → EAS Submit`

backend/scripts/backup-deployment-db.ps1 renamed to Old Scripts/backend/scripts/backup-deployment-db.ps1

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@ param(
55

66
$ErrorActionPreference = "Stop"
77

8-
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
9-
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
10-
Start-Process powershell -Verb runAs -ArgumentList $arguments
11-
exit
12-
}
13-
148
Write-Host "Creating deployment database backup..." -ForegroundColor Yellow
159

1610
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
@@ -21,23 +15,28 @@ try {
2115
New-Item -ItemType Directory -Path $backupPath -Force | Out-Null
2216

2317
$envFile = Join-Path $root ".env"
24-
$dbUser = "devbits"
25-
$dbName = "devbits"
26-
if (Test-Path $envFile) {
27-
$envRaw = Get-Content -Path $envFile -Raw
28-
if ($envRaw -match "(?m)^POSTGRES_USER=(.+)$") {
29-
$dbUser = $Matches[1].Trim()
30-
}
31-
if ($envRaw -match "(?m)^POSTGRES_DB=(.+)$") {
32-
$dbName = $Matches[1].Trim()
33-
}
18+
if (-not (Test-Path $envFile)) {
19+
throw "Missing $envFile. Create it from backend/.env.example and set DATABASE_URL."
20+
}
21+
22+
$envRaw = Get-Content -Path $envFile -Raw
23+
$dbUrl = $null
24+
if ($envRaw -match "(?m)^DATABASE_URL=(.+)$") {
25+
$dbUrl = $Matches[1].Trim()
26+
}
27+
if ([string]::IsNullOrWhiteSpace($dbUrl)) {
28+
throw "Missing DATABASE_URL in $envFile"
29+
}
30+
31+
if (-not (Get-Command pg_dump -ErrorAction SilentlyContinue)) {
32+
throw "pg_dump not found in PATH. Install PostgreSQL client tools first."
3433
}
3534

3635
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
3736
$dbBackupFileName = "devbits-db-$timestamp.sql"
3837
$dbBackupFile = Join-Path $backupPath $dbBackupFileName
39-
40-
docker compose exec -T db pg_dump -U $dbUser -d $dbName --no-owner --no-privileges | Out-File -FilePath $dbBackupFile -Encoding utf8
38+
39+
pg_dump $dbUrl --no-owner --no-privileges | Out-File -FilePath $dbBackupFile -Encoding utf8
4140

4241
if (-not (Test-Path $dbBackupFile)) {
4342
throw "Database backup file was not created."
@@ -69,20 +68,11 @@ finally {
6968
Pop-Location
7069
}
7170

72-
$liveBackendState = "unavailable"
73-
try {
74-
$statusOutput = docker compose -f (Join-Path $root "docker-compose.yml") ps backend 2>$null
75-
if ($LASTEXITCODE -eq 0) {
76-
$liveBackendState = if (($statusOutput | Out-String) -match "Up") { "running" } else { "not running" }
77-
}
78-
}
79-
catch {}
80-
8171
Write-Host ""
8272
Write-Host "===== Summary =====" -ForegroundColor Cyan
8373
Write-Host "Action: Deployment backup created"
8474
Write-Host "Updated: Latest DB + uploads backup files retained"
85-
Write-Host "Live backend: $liveBackendState"
75+
Write-Host "Database backup target: DATABASE_URL"
8676

8777
if (-not $NoPause -and [Environment]::UserInteractive -and $Host.Name -eq "ConsoleHost") {
8878
Read-Host "Press Enter to close"

backend/scripts/disable-daily-backup-task.ps1 renamed to Old Scripts/backend/scripts/disable-daily-backup-task.ps1

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,12 @@ Write-Host "Task removed." -ForegroundColor Green
2323

2424
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
2525
$root = Resolve-Path (Join-Path $scriptDir "..")
26-
$liveBackendState = "unavailable"
27-
try {
28-
$statusOutput = docker compose -f (Join-Path $root "docker-compose.yml") ps backend 2>$null
29-
if ($LASTEXITCODE -eq 0) {
30-
$liveBackendState = if (($statusOutput | Out-String) -match "Up") { "running" } else { "not running" }
31-
}
32-
}
33-
catch {}
3426

3527
Write-Host ""
3628
Write-Host "===== Summary =====" -ForegroundColor Cyan
3729
Write-Host "Action: Daily backup task removed"
3830
Write-Host "Updated: Windows scheduled task '$TaskName' deleted"
39-
Write-Host "Live backend: $liveBackendState"
31+
Write-Host "Execution target removed: backup-deployment-db.ps1"
4032

4133
if (-not $NoPause -and [Environment]::UserInteractive -and $Host.Name -eq "ConsoleHost") {
4234
Read-Host "Press Enter to close"

0 commit comments

Comments
 (0)