Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
FROM node:20-bookworm-slim AS build
FROM node:24-bookworm-slim AS build

WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm ci

COPY . .
RUN npm run build
RUN npm prune --omit=dev

FROM node:20-bookworm-slim AS runtime
FROM node:24-bookworm-slim AS runtime

WORKDIR /app
ENV NODE_ENV=production
Expand All @@ -18,8 +18,10 @@ ENV DATA_DIR=/app/data
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh

RUN mkdir -p /app/data
RUN mkdir -p /app/data && chown node:node /app/data && chmod 700 /app/data && chmod +x /usr/local/bin/entrypoint.sh

EXPOSE 8787
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["node", "dist/server/server/index.js"]
215 changes: 81 additions & 134 deletions README.md

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions docker-compose.coolify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Coolify deployment (Docker Compose resource from this Git repository).
#
# Coolify's proxy (Traefik by default) terminates TLS and routes the domain you set on the `app`
# service in the Coolify UI to the exposed port. Do not publish host ports here; Coolify reaches
# the container over the resource's own Docker network, so only Coolify's proxy and this service
# share it. The magic variable SERVICE_URL_APP is filled by Coolify with that domain's URL.
services:
app:
build:
context: .
restart: unless-stopped
environment:
NODE_ENV: production
TZ: ${TZ:-Etc/UTC}
PORT: 8787
DATA_DIR: /app/data
# Required. Encrypts stored wallet passwords, node keys, and status tokens. Never change it
# after operators have registered. Generate with: openssl rand -hex 32
APP_SECRET: ${APP_SECRET:?Set APP_SECRET in the Coolify environment variables}
# Coolify serves the app over HTTPS, so the session cookie is TLS-only.
COOKIE_SECURE: "true"
# Fixed public origin used in generated bootstrap scripts and manifests. Defaults to the
# domain configured for this service in Coolify.
PUBLIC_URL: ${PUBLIC_URL:-${SERVICE_URL_APP}}
# Coolify's proxy reaches the app over a private Docker network dedicated to this resource.
TRUST_PROXY: ${TRUST_PROXY:-uniquelocal}
GO_ZENON_REPO: ${GO_ZENON_REPO:-https://github.com/zenon-network/go-zenon.git}
GO_ZENON_REF: ${GO_ZENON_REF:-master}
GO_ZENON_COMMIT: ${GO_ZENON_COMMIT:-}
DEPLOYMENT_REPO: ${DEPLOYMENT_REPO:-https://github.com/hypercore-one/deployment.git}
DEPLOYMENT_REF: ${DEPLOYMENT_REF:-main}
DEPLOYMENT_COMMIT: ${DEPLOYMENT_COMMIT:-}
ALLOWED_REPO_HOSTS: ${ALLOWED_REPO_HOSTS:-github.com}
ALLOWED_REPOS: ${ALLOWED_REPOS:-}
expose:
- "8787"
volumes:
- testnet-data:/app/data
healthcheck:
test:
[
"CMD-SHELL",
"node -e \"fetch('http://127.0.0.1:8787/api/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""
]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s

volumes:
testnet-data:
48 changes: 0 additions & 48 deletions docker-compose.portainer.yml

This file was deleted.

12 changes: 11 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ services:
GO_ZENON_REF: ${GO_ZENON_REF:-master}
DEPLOYMENT_REPO: ${DEPLOYMENT_REPO:-https://github.com/hypercore-one/deployment.git}
DEPLOYMENT_REF: ${DEPLOYMENT_REF:-main}
PUBLIC_URL: ${PUBLIC_URL:-}
ALLOWED_REPO_HOSTS: ${ALLOWED_REPO_HOSTS:-github.com}
DEPLOYMENT_COMMIT: ${DEPLOYMENT_COMMIT:-}
GO_ZENON_COMMIT: ${GO_ZENON_COMMIT:-}
# Caddy reaches the app over the private Docker network; only peers in private ranges may set X-Forwarded-*.
TRUST_PROXY: ${TRUST_PROXY:-uniquelocal}
ALLOWED_REPOS: ${ALLOWED_REPOS:-}
COOKIE_SECURE: ${COOKIE_SECURE:-false}
volumes:
- testnet-data:/app/data

Expand All @@ -19,7 +27,9 @@ services:
depends_on:
- app
ports:
- "${HTTP_PORT:-8080}:80"
# This stack serves plain HTTP, so it only listens on localhost by default. Put a TLS
# terminating proxy in front and set HTTP_BIND=0.0.0.0 to expose it on other interfaces.
- "${HTTP_BIND:-127.0.0.1}:${HTTP_PORT:-8080}:80"
volumes:
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
Expand Down
16 changes: 16 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh
# Runs the app as the unprivileged "node" user. When the container starts as root (the default,
# so that a data volume created by an older root-only image keeps working), fix ownership of the
# data directory and then drop privileges before starting Node.
set -eu

DATA_DIR="${DATA_DIR:-/app/data}"
mkdir -p "$DATA_DIR"

if [ "$(id -u)" = "0" ]; then
chown -R node:node "$DATA_DIR"
chmod 700 "$DATA_DIR"
exec setpriv --reuid=node --regid=node --init-groups "$@"
fi

exec "$@"
89 changes: 45 additions & 44 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"build:web": "vite build",
"start": "node dist/server/server/index.js",
"account": "tsx src/server/cli.ts",
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p tsconfig.web.json --noEmit"
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p tsconfig.test.json --noEmit && tsc -p tsconfig.web.json --noEmit",
"test": "tsx --test src/server/*.test.ts"
},
"dependencies": {
"@vitejs/plugin-react": "^4.3.4",
Expand All @@ -37,5 +38,9 @@
"tsx": "^4.19.2",
"typescript": "^5.7.2",
"vite": "^6.0.3"
},
"overrides": {
"ws": "^8.21.0",
"qs": "^6.16.0"
}
}
Loading