@hasna/shortlinks 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/infra/aws-ec2-user-data.sh +168 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -138,6 +138,17 @@ shortlinks cloud sync
|
|
|
138
138
|
|
|
139
139
|
The cloud database service name is `shortlinks`.
|
|
140
140
|
|
|
141
|
+
## AWS Origin
|
|
142
|
+
|
|
143
|
+
For an apex domain that needs stable A records, `infra/aws-ec2-user-data.sh` bootstraps a small EC2 redirect origin with:
|
|
144
|
+
|
|
145
|
+
- `@hasna/shortlinks` installed through Bun
|
|
146
|
+
- local SQLite data synced with the `shortlinks` RDS database through `@hasna/cloud`
|
|
147
|
+
- Caddy terminating HTTPS and proxying to `shortlinks serve`
|
|
148
|
+
- a systemd timer that syncs links and clicks every minute
|
|
149
|
+
|
|
150
|
+
The script reads the RDS password from AWS Secrets Manager through the instance role; it does not contain secret values.
|
|
151
|
+
|
|
141
152
|
## Development
|
|
142
153
|
|
|
143
154
|
```bash
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
export AWS_REGION="${AWS_REGION:-us-east-1}"
|
|
5
|
+
export SHORTLINKS_HOME="/var/lib/shortlinks"
|
|
6
|
+
export SHORTLINKS_PACKAGE="@hasna/shortlinks@latest"
|
|
7
|
+
export RDS_SECRET_ID="rds!db-7a451ce6-83a9-40fa-b24a-81e5d5943511"
|
|
8
|
+
export RDS_HOST="hasnaxyz-prod-opensource.c4limg0qgqvk.us-east-1.rds.amazonaws.com"
|
|
9
|
+
export RDS_USERNAME="hasna_admin"
|
|
10
|
+
|
|
11
|
+
dnf update -y
|
|
12
|
+
dnf install -y awscli jq tar gzip shadow-utils libcap
|
|
13
|
+
|
|
14
|
+
if ! id shortlinks >/dev/null 2>&1; then
|
|
15
|
+
useradd --system --create-home --home-dir "${SHORTLINKS_HOME}" --shell /sbin/nologin shortlinks
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/cloud"
|
|
19
|
+
install -d -o shortlinks -g shortlinks "${SHORTLINKS_HOME}/.hasna/shortlinks"
|
|
20
|
+
|
|
21
|
+
cat > "${SHORTLINKS_HOME}/.hasna/cloud/config.json" <<CLOUD_CONFIG
|
|
22
|
+
{
|
|
23
|
+
"rds": {
|
|
24
|
+
"host": "${RDS_HOST}",
|
|
25
|
+
"port": 5432,
|
|
26
|
+
"username": "${RDS_USERNAME}",
|
|
27
|
+
"password_env": "HASNA_RDS_PASSWORD",
|
|
28
|
+
"ssl": true
|
|
29
|
+
},
|
|
30
|
+
"mode": "hybrid",
|
|
31
|
+
"feedback_endpoint": "https://feedback.hasna.com/api/v1/feedback",
|
|
32
|
+
"auto_sync_interval_minutes": 0,
|
|
33
|
+
"sync": {
|
|
34
|
+
"schedule_minutes": 0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
CLOUD_CONFIG
|
|
38
|
+
chown shortlinks:shortlinks "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
|
|
39
|
+
chmod 600 "${SHORTLINKS_HOME}/.hasna/cloud/config.json"
|
|
40
|
+
|
|
41
|
+
su -s /bin/bash shortlinks -c 'curl -fsSL https://bun.sh/install | bash'
|
|
42
|
+
su -s /bin/bash shortlinks -c "${SHORTLINKS_HOME}/.bun/bin/bun install -g ${SHORTLINKS_PACKAGE} --no-cache"
|
|
43
|
+
|
|
44
|
+
cat > /usr/local/bin/shortlinks-env-exec <<'RUNNER'
|
|
45
|
+
#!/usr/bin/env bash
|
|
46
|
+
set -euo pipefail
|
|
47
|
+
|
|
48
|
+
export AWS_REGION="${AWS_REGION:-us-east-1}"
|
|
49
|
+
export HOME="/var/lib/shortlinks"
|
|
50
|
+
export PATH="/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin"
|
|
51
|
+
export NODE_TLS_REJECT_UNAUTHORIZED="0"
|
|
52
|
+
|
|
53
|
+
secret_json="$(aws secretsmanager get-secret-value \
|
|
54
|
+
--region "${AWS_REGION}" \
|
|
55
|
+
--secret-id "rds!db-7a451ce6-83a9-40fa-b24a-81e5d5943511" \
|
|
56
|
+
--query SecretString \
|
|
57
|
+
--output text)"
|
|
58
|
+
|
|
59
|
+
export HASNA_RDS_PASSWORD
|
|
60
|
+
HASNA_RDS_PASSWORD="$(jq -r '.password' <<<"${secret_json}")"
|
|
61
|
+
|
|
62
|
+
exec "$@"
|
|
63
|
+
RUNNER
|
|
64
|
+
chmod 750 /usr/local/bin/shortlinks-env-exec
|
|
65
|
+
chown root:shortlinks /usr/local/bin/shortlinks-env-exec
|
|
66
|
+
|
|
67
|
+
su -s /bin/bash shortlinks -c '/usr/local/bin/shortlinks-env-exec shortlinks --json doctor'
|
|
68
|
+
su -s /bin/bash shortlinks -c '/usr/local/bin/shortlinks-env-exec shortlinks --json config set default-domain has.na'
|
|
69
|
+
su -s /bin/bash shortlinks -c '/usr/local/bin/shortlinks-env-exec shortlinks --json cloud pull --tables domains,links,clicks' || true
|
|
70
|
+
|
|
71
|
+
caddy_version="$(curl -fsSL https://api.github.com/repos/caddyserver/caddy/releases/latest | jq -r '.tag_name // "v2.10.2"' | sed 's/^v//')"
|
|
72
|
+
case "$(uname -m)" in
|
|
73
|
+
aarch64|arm64) caddy_arch="arm64" ;;
|
|
74
|
+
x86_64|amd64) caddy_arch="amd64" ;;
|
|
75
|
+
*) caddy_arch="arm64" ;;
|
|
76
|
+
esac
|
|
77
|
+
curl -fsSL -o /tmp/caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v${caddy_version}/caddy_${caddy_version}_linux_${caddy_arch}.tar.gz"
|
|
78
|
+
tar -xzf /tmp/caddy.tar.gz -C /tmp caddy
|
|
79
|
+
install -m 0755 /tmp/caddy /usr/local/bin/caddy
|
|
80
|
+
setcap cap_net_bind_service=+ep /usr/local/bin/caddy || true
|
|
81
|
+
|
|
82
|
+
cat > /etc/systemd/system/shortlinks.service <<'SERVICE'
|
|
83
|
+
[Unit]
|
|
84
|
+
Description=Shortlinks redirect server
|
|
85
|
+
After=network-online.target
|
|
86
|
+
Wants=network-online.target
|
|
87
|
+
|
|
88
|
+
[Service]
|
|
89
|
+
Type=simple
|
|
90
|
+
User=shortlinks
|
|
91
|
+
Group=shortlinks
|
|
92
|
+
WorkingDirectory=/var/lib/shortlinks
|
|
93
|
+
Environment=HOME=/var/lib/shortlinks
|
|
94
|
+
Environment=PATH=/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin
|
|
95
|
+
ExecStartPre=/usr/local/bin/shortlinks-env-exec shortlinks --json cloud pull --tables domains,links
|
|
96
|
+
ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks serve --host 127.0.0.1 --port 8787 --default-host has.na
|
|
97
|
+
Restart=always
|
|
98
|
+
RestartSec=5
|
|
99
|
+
|
|
100
|
+
[Install]
|
|
101
|
+
WantedBy=multi-user.target
|
|
102
|
+
SERVICE
|
|
103
|
+
|
|
104
|
+
cat > /etc/systemd/system/shortlinks-sync.service <<'SERVICE'
|
|
105
|
+
[Unit]
|
|
106
|
+
Description=Sync shortlinks SQLite data with RDS
|
|
107
|
+
After=network-online.target
|
|
108
|
+
Wants=network-online.target
|
|
109
|
+
|
|
110
|
+
[Service]
|
|
111
|
+
Type=oneshot
|
|
112
|
+
User=shortlinks
|
|
113
|
+
Group=shortlinks
|
|
114
|
+
WorkingDirectory=/var/lib/shortlinks
|
|
115
|
+
Environment=HOME=/var/lib/shortlinks
|
|
116
|
+
Environment=PATH=/var/lib/shortlinks/.bun/bin:/usr/local/bin:/usr/bin:/bin
|
|
117
|
+
ExecStart=/usr/local/bin/shortlinks-env-exec shortlinks --json cloud sync --tables domains,links,clicks
|
|
118
|
+
SERVICE
|
|
119
|
+
|
|
120
|
+
cat > /etc/systemd/system/shortlinks-sync.timer <<'TIMER'
|
|
121
|
+
[Unit]
|
|
122
|
+
Description=Run shortlinks cloud sync every minute
|
|
123
|
+
|
|
124
|
+
[Timer]
|
|
125
|
+
OnBootSec=2min
|
|
126
|
+
OnUnitActiveSec=1min
|
|
127
|
+
Unit=shortlinks-sync.service
|
|
128
|
+
|
|
129
|
+
[Install]
|
|
130
|
+
WantedBy=timers.target
|
|
131
|
+
TIMER
|
|
132
|
+
|
|
133
|
+
cat > /etc/systemd/system/caddy.service <<'SERVICE'
|
|
134
|
+
[Unit]
|
|
135
|
+
Description=Caddy web server for shortlinks
|
|
136
|
+
After=network-online.target shortlinks.service
|
|
137
|
+
Wants=network-online.target
|
|
138
|
+
|
|
139
|
+
[Service]
|
|
140
|
+
Type=simple
|
|
141
|
+
User=root
|
|
142
|
+
Group=root
|
|
143
|
+
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
|
|
144
|
+
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
|
|
145
|
+
TimeoutStopSec=5s
|
|
146
|
+
LimitNOFILE=1048576
|
|
147
|
+
PrivateTmp=true
|
|
148
|
+
ProtectSystem=full
|
|
149
|
+
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
150
|
+
Restart=on-failure
|
|
151
|
+
|
|
152
|
+
[Install]
|
|
153
|
+
WantedBy=multi-user.target
|
|
154
|
+
SERVICE
|
|
155
|
+
|
|
156
|
+
install -d /etc/caddy
|
|
157
|
+
cat > /etc/caddy/Caddyfile <<'CADDY'
|
|
158
|
+
has.na {
|
|
159
|
+
encode zstd gzip
|
|
160
|
+
reverse_proxy 127.0.0.1:8787
|
|
161
|
+
}
|
|
162
|
+
CADDY
|
|
163
|
+
|
|
164
|
+
systemctl daemon-reload
|
|
165
|
+
systemctl enable shortlinks.service shortlinks-sync.timer caddy.service
|
|
166
|
+
systemctl start shortlinks.service
|
|
167
|
+
systemctl start shortlinks-sync.timer
|
|
168
|
+
systemctl start caddy.service || true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/shortlinks",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "CLI-only shortlink manager for custom domains, click tracking, Cloudflare setup, and @hasna cloud sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"cloudflare",
|
|
28
|
+
"infra",
|
|
28
29
|
"LICENSE",
|
|
29
30
|
"README.md",
|
|
30
31
|
"SECURITY.md"
|