Skip to content

Commit 3ebb6b6

Browse files
ampagentarjunkomath
andcommitted
Replace bundled registry with user-owned Google Artifact Registry
Amp-Thread-ID: https://ampcode.com/threads/T-01a05ff5-ad1a-7058-8fbe-bc5814e87049 Co-authored-by: Arjun Komath <arjunkomath@gmail.com>
1 parent 22a065c commit 3ebb6b6

52 files changed

Lines changed: 2166 additions & 1290 deletions

Some content is hidden

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

‎.github/workflows/release.yml‎

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,12 @@ jobs:
160160
compose_production=$(sha256sum deployment/compose.production.yml | awk '{print $1}')
161161
compose_postgres=$(sha256sum deployment/compose.postgres.yml | awk '{print $1}')
162162
web_digest=$(cat image-digests/web)
163-
registry_digest=$(cat image-digests/registry)
164163
updater_digest=$(cat image-digests/updater)
165164
166165
for checksum in "$agent_amd64" "$agent_arm64" "$compose_production" "$compose_postgres"; do
167166
[[ "$checksum" =~ $sha256_pattern ]]
168167
done
169-
for digest in "$web_digest" "$registry_digest" "$updater_digest"; do
168+
for digest in "$web_digest" "$updater_digest"; do
170169
[[ "$digest" =~ $digest_pattern ]]
171170
done
172171
[[ "$RELEASE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]
@@ -180,7 +179,6 @@ jobs:
180179
--arg compose_production "$compose_production" \
181180
--arg compose_postgres "$compose_postgres" \
182181
--arg web_digest "$web_digest" \
183-
--arg registry_digest "$registry_digest" \
184182
--arg updater_digest "$updater_digest" \
185183
'{
186184
version: $version,
@@ -195,7 +193,6 @@ jobs:
195193
},
196194
images: {
197195
web: $web_digest,
198-
registry: $registry_digest,
199196
updater: $updater_digest
200197
}
201198
}' > binaries/release-manifest.json
@@ -331,16 +328,6 @@ jobs:
331328
arch: arm64
332329
platform: linux/arm64
333330
runner: blacksmith-2vcpu-ubuntu-2404-arm
334-
- image: registry
335-
context: registry
336-
arch: amd64
337-
platform: linux/amd64
338-
runner: blacksmith-2vcpu-ubuntu-2404
339-
- image: registry
340-
context: registry
341-
arch: arm64
342-
platform: linux/arm64
343-
runner: blacksmith-2vcpu-ubuntu-2404-arm
344331
- image: updater
345332
context: deployment/updater
346333
arch: amd64
@@ -397,7 +384,7 @@ jobs:
397384
runs-on: blacksmith-2vcpu-ubuntu-2404
398385
strategy:
399386
matrix:
400-
image: [web, registry, updater]
387+
image: [web, updater]
401388

402389
steps:
403390
- name: Download digests

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ An open container deployment platform. See README.md for architecture.
1616
- `agent/` — Go server agent (Podman, Traefik, WireGuard)
1717
- `cli/` — Go CLI
1818
- `deployment/` — production Compose files and updater
19-
- `proxy/`, `registry/`, `logging/` — supporting service configs
19+
- `proxy/`, `logging/` — supporting service configs
2020
- `docs/` — documentation
2121

2222
## Commands

‎README.md‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ A container deployment platform with private-first networking.
1515

1616
## Tech Stack
1717

18-
| Component | Technology |
19-
|-----------|------------|
20-
| Control Plane | Next.js (full-stack) |
21-
| Database | PostgreSQL + Drizzle |
22-
| Server Agent | Go |
23-
| Container Runtime | Podman |
24-
| Reverse Proxy | Traefik |
25-
| Private Network | WireGuard |
18+
| Component | Technology |
19+
| --------------------- | ----------------------------------- |
20+
| Control Plane | Next.js (full-stack) |
21+
| Database | PostgreSQL + Drizzle |
22+
| Server Agent | Go |
23+
| Container Runtime | Podman |
24+
| Reverse Proxy | Traefik |
25+
| Private Network | WireGuard |
26+
| Source Image Registry | User-owned Google Artifact Registry |
2627

2728
## How It Works
2829

@@ -47,13 +48,17 @@ flowchart LR
4748
```
4849

4950
**Traffic Flow:**
51+
5052
- **Public**: Internet → Proxy Node → Traefik (TLS) → WireGuard → Container
5153
- **Internal**: Container → DNS (.internal) → WireGuard → Container
5254

5355
## Architecture
5456

5557
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed documentation.
5658

59+
Self-hosted installations require a user-owned Google Artifact Registry Docker
60+
repository. See the [registry setup guide](docs/infrastructure/registry.mdx).
61+
5762
## TODO
5863

5964
- Notifications: Alert channels for deployment events and system alerts

‎compose.dev.yml‎

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,6 @@ services:
1515
timeout: 5s
1616
retries: 5
1717

18-
registry:
19-
build:
20-
context: ./registry
21-
dockerfile: Dockerfile
22-
environment:
23-
REGISTRY_USERNAME: docker
24-
REGISTRY_PASSWORD: docker
25-
ports:
26-
- "5002:5000"
27-
volumes:
28-
- registry-data:/var/lib/registry
29-
healthcheck:
30-
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:5001/debug/health"]
31-
interval: 30s
32-
timeout: 10s
33-
retries: 3
34-
restart: unless-stopped
35-
3618
victoria-logs:
3719
image: victoriametrics/victoria-logs:v1.51.0
3820
ports:
@@ -83,7 +65,6 @@ services:
8365
restart: unless-stopped
8466

8567
volumes:
86-
registry-data:
8768
victoria-logs-data:
8869
victoria-metrics-data:
8970
postgres_data:

‎deployment/.env.example‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@ VM_USERNAME=admin
2929
VM_PASSWORD=your-secure-metrics-password
3030
VM_RETENTION=30d
3131

32-
# Registry
33-
REGISTRY_URL=registry:5000
34-
REGISTRY_USERNAME=admin
35-
REGISTRY_PASSWORD=your-registry-password
36-
REGISTRY_HTTP_SECRET=your-registry-http-secret
32+
# Google Artifact Registry (required)
33+
GAR_REPOSITORY=us-central1-docker.pkg.dev/google-project/techulus-images
34+
GAR_AGENT_KEY_BASE64=base64-encoded-writer-service-account-json
35+
GAR_ADMIN_KEY_BASE64=base64-encoded-repository-admin-service-account-json
3736

3837
# Inngest
3938
INNGEST_SIGNING_KEY=signkey-xxx
@@ -48,7 +47,6 @@ COMPOSE_FILE=compose.production.yml
4847
# The installer and updater populate immutable release image references.
4948
# When these image references are omitted, Compose uses TECHULUS_CLOUD_VERSION.
5049
# TECHULUS_CLOUD_WEB_IMAGE=ghcr.io/techulus/cloud/web@sha256:...
51-
# TECHULUS_CLOUD_REGISTRY_IMAGE=ghcr.io/techulus/cloud/registry@sha256:...
5250
# TECHULUS_CLOUD_UPDATER_IMAGE=ghcr.io/techulus/cloud/updater@sha256:...
5351
CONTROL_PLANE_UPDATER_TOKEN=generate-with-openssl-rand-hex-32
5452

‎deployment/README.md‎

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
Docker Compose setup with Traefik for SSL termination via Let's Encrypt.
44

5+
A user-owned Google Artifact Registry Docker repository is mandatory. Complete
6+
the [GAR setup](../docs/infrastructure/registry.mdx), including its two
7+
repository-scoped service accounts and cleanup policy, before starting Compose.
8+
The recommended `setup-gar.sh` helper runs from Google Cloud Shell or a trusted
9+
workstation with an authenticated `gcloud` CLI, not from the control plane or
10+
production containers.
11+
512
## Quick Start
613

714
```bash
@@ -41,23 +48,26 @@ unhealthy containers but does not restart them automatically.
4148

4249
## Services
4350

44-
| Service | Endpoint |
45-
|---------|----------|
46-
| Web | `https://${ROOT_DOMAIN}` |
47-
| Registry | `https://registry.${ROOT_DOMAIN}` |
48-
| Logs | `https://logs.${ROOT_DOMAIN}` |
49-
| PostgreSQL | Internal only |
50-
| Inngest | Internal only |
51+
| Service | Endpoint |
52+
| ---------- | ----------------------------- |
53+
| Web | `https://${ROOT_DOMAIN}` |
54+
| Logs | `https://logs.${ROOT_DOMAIN}` |
55+
| PostgreSQL | Internal only |
56+
| Inngest | Internal only |
5157

5258
## Environment Setup
5359

54-
Generate registry auth:
55-
```bash
56-
htpasswd -nB admin
57-
# Escape $ as $$ in .env
58-
```
60+
Set `GAR_REPOSITORY`, `GAR_AGENT_KEY_BASE64`, and `GAR_ADMIN_KEY_BASE64` in
61+
`.env`. The installer reads key values without terminal echo. Agents receive
62+
only the Writer credential; the Repository Administrator key stays in the web
63+
service.
64+
65+
Upgrades do not migrate images from the former bundled registry. Rebuild every
66+
source-backed service after upgrading. The old `registry-data` Docker volume is
67+
left untouched for explicit operator cleanup after the cutover is verified.
5968

6069
Generate Inngest keys:
70+
6171
```bash
6272
# Signing key (for request verification)
6373
openssl rand -hex 32
@@ -68,6 +78,7 @@ openssl rand -hex 16
6878
```
6979

7080
Add to `.env`:
81+
7182
```
7283
INNGEST_SIGNING_KEY=signkey-prod-<your-signing-key>
7384
INNGEST_EVENT_KEY=<your-event-key>

‎deployment/compose.postgres.yml‎

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ services:
8282
- VICTORIA_LOGS_PRIVATE_URL=http://${VL_USERNAME}:${VL_PASSWORD}@victoria-logs:9428
8383
- VICTORIA_METRICS_URL=https://${VM_USERNAME}:${VM_PASSWORD}@metrics.${ROOT_DOMAIN}
8484
- VICTORIA_METRICS_PRIVATE_URL=http://${VM_USERNAME}:${VM_PASSWORD}@victoria-metrics:8428
85-
- REGISTRY_HOST=registry.${ROOT_DOMAIN}
8685
- INNGEST_BASE_URL=http://inngest:8288
8786
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
8887
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
@@ -109,8 +108,9 @@ services:
109108
- VICTORIA_LOGS_PRIVATE_URL=http://${VL_USERNAME}:${VL_PASSWORD}@victoria-logs:9428
110109
- VICTORIA_METRICS_URL=https://${VM_USERNAME}:${VM_PASSWORD}@metrics.${ROOT_DOMAIN}
111110
- VICTORIA_METRICS_PRIVATE_URL=http://${VM_USERNAME}:${VM_PASSWORD}@victoria-metrics:8428
112-
- REGISTRY_URL=${REGISTRY_URL:-registry:5000}
113-
- REGISTRY_HOST=registry.${ROOT_DOMAIN}
111+
- GAR_REPOSITORY=${GAR_REPOSITORY:?GAR_REPOSITORY is required}
112+
- GAR_AGENT_KEY_BASE64=${GAR_AGENT_KEY_BASE64:?GAR_AGENT_KEY_BASE64 is required}
113+
- GAR_ADMIN_KEY_BASE64=${GAR_ADMIN_KEY_BASE64:?GAR_ADMIN_KEY_BASE64 is required}
114114
- INNGEST_BASE_URL=http://inngest:8288
115115
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
116116
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
@@ -124,8 +124,6 @@ services:
124124
condition: service_started
125125
victoria-metrics:
126126
condition: service_started
127-
registry:
128-
condition: service_started
129127
labels:
130128
- "traefik.enable=true"
131129
- "traefik.http.routers.web.rule=Host(`${ROOT_DOMAIN}`)"
@@ -162,25 +160,6 @@ services:
162160
retries: 3
163161
restart: unless-stopped
164162

165-
registry:
166-
image: "${TECHULUS_CLOUD_REGISTRY_IMAGE:-ghcr.io/techulus/cloud/registry:${TECHULUS_CLOUD_VERSION:?TECHULUS_CLOUD_VERSION is required}}"
167-
env_file:
168-
- ./.env
169-
volumes:
170-
- registry-data:/var/lib/registry
171-
labels:
172-
- "traefik.enable=true"
173-
- "traefik.http.routers.registry.rule=Host(`registry.${ROOT_DOMAIN}`)"
174-
- "traefik.http.routers.registry.entrypoints=websecure"
175-
- "traefik.http.routers.registry.tls.certresolver=letsencrypt"
176-
- "traefik.http.services.registry.loadbalancer.server.port=5000"
177-
healthcheck:
178-
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:5001/debug/health"]
179-
interval: 30s
180-
timeout: 10s
181-
retries: 3
182-
restart: unless-stopped
183-
184163
victoria-logs:
185164
image: victoriametrics/victoria-logs:v1.51.0
186165
env_file:
@@ -257,7 +236,6 @@ services:
257236
volumes:
258237
letsencrypt:
259238
postgres-data:
260-
registry-data:
261239
victoria-logs-data:
262240
victoria-metrics-data:
263241
inngest-data:

‎deployment/compose.production.yml‎

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ services:
6464
- VICTORIA_LOGS_PRIVATE_URL=http://${VL_USERNAME}:${VL_PASSWORD}@victoria-logs:9428
6565
- VICTORIA_METRICS_URL=https://${VM_USERNAME}:${VM_PASSWORD}@metrics.${ROOT_DOMAIN}
6666
- VICTORIA_METRICS_PRIVATE_URL=http://${VM_USERNAME}:${VM_PASSWORD}@victoria-metrics:8428
67-
- REGISTRY_HOST=registry.${ROOT_DOMAIN}
6867
- INNGEST_BASE_URL=http://inngest:8288
6968
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
7069
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
@@ -88,8 +87,9 @@ services:
8887
- VICTORIA_LOGS_PRIVATE_URL=http://${VL_USERNAME}:${VL_PASSWORD}@victoria-logs:9428
8988
- VICTORIA_METRICS_URL=https://${VM_USERNAME}:${VM_PASSWORD}@metrics.${ROOT_DOMAIN}
9089
- VICTORIA_METRICS_PRIVATE_URL=http://${VM_USERNAME}:${VM_PASSWORD}@victoria-metrics:8428
91-
- REGISTRY_URL=${REGISTRY_URL:-registry:5000}
92-
- REGISTRY_HOST=registry.${ROOT_DOMAIN}
90+
- GAR_REPOSITORY=${GAR_REPOSITORY:?GAR_REPOSITORY is required}
91+
- GAR_AGENT_KEY_BASE64=${GAR_AGENT_KEY_BASE64:?GAR_AGENT_KEY_BASE64 is required}
92+
- GAR_ADMIN_KEY_BASE64=${GAR_ADMIN_KEY_BASE64:?GAR_ADMIN_KEY_BASE64 is required}
9393
- INNGEST_BASE_URL=http://inngest:8288
9494
- INNGEST_SIGNING_KEY=${INNGEST_SIGNING_KEY}
9595
- INNGEST_EVENT_KEY=${INNGEST_EVENT_KEY}
@@ -103,8 +103,6 @@ services:
103103
condition: service_started
104104
victoria-metrics:
105105
condition: service_started
106-
registry:
107-
condition: service_started
108106
labels:
109107
- "traefik.enable=true"
110108
- "traefik.http.routers.web.rule=Host(`${ROOT_DOMAIN}`)"
@@ -141,25 +139,6 @@ services:
141139
retries: 3
142140
restart: unless-stopped
143141

144-
registry:
145-
image: "${TECHULUS_CLOUD_REGISTRY_IMAGE:-ghcr.io/techulus/cloud/registry:${TECHULUS_CLOUD_VERSION:?TECHULUS_CLOUD_VERSION is required}}"
146-
env_file:
147-
- ./.env
148-
volumes:
149-
- registry-data:/var/lib/registry
150-
labels:
151-
- "traefik.enable=true"
152-
- "traefik.http.routers.registry.rule=Host(`registry.${ROOT_DOMAIN}`)"
153-
- "traefik.http.routers.registry.entrypoints=websecure"
154-
- "traefik.http.routers.registry.tls.certresolver=letsencrypt"
155-
- "traefik.http.services.registry.loadbalancer.server.port=5000"
156-
healthcheck:
157-
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:5001/debug/health"]
158-
interval: 30s
159-
timeout: 10s
160-
retries: 3
161-
restart: unless-stopped
162-
163142
victoria-logs:
164143
image: victoriametrics/victoria-logs:v1.51.0
165144
env_file:
@@ -235,7 +214,6 @@ services:
235214

236215
volumes:
237216
letsencrypt:
238-
registry-data:
239217
victoria-logs-data:
240218
victoria-metrics-data:
241219
inngest-data:

‎deployment/gar-cleanup-policy.json‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[
2+
{
3+
"name": "keep-techulus-protected",
4+
"action": {
5+
"type": "Keep"
6+
},
7+
"condition": {
8+
"tagState": "tagged",
9+
"tagPrefixes": ["protected-"]
10+
}
11+
},
12+
{
13+
"name": "keep-ten-most-recent",
14+
"action": {
15+
"type": "Keep"
16+
},
17+
"mostRecentVersions": {
18+
"keepCount": 10
19+
}
20+
},
21+
{
22+
"name": "delete-unprotected-after-thirty-days",
23+
"action": {
24+
"type": "Delete"
25+
},
26+
"condition": {
27+
"tagState": "any",
28+
"olderThan": "30d"
29+
}
30+
}
31+
]

0 commit comments

Comments
 (0)