Deploying Embetty Server

The recommended method for deploying embetty-server is using the official Docker image. This provides a self-contained, consistent, and isolated environment for the application.

Docker Deployment

The official image is hosted on Docker Hub: heiseonline/embetty-server.

The image is built for multiple platforms (linux/amd64 and linux/arm64), making it suitable for a wide range of server architectures.

Running the Container

To run the server, use the docker run command. You must map a host port to the container's port 8080 and provide the necessary environment variables for configuration.

docker run -d \
  -p 8080:8080 \
  --name embetty-server \
  --restart always \
  -e VALID_ORIGINS="https://your-website.com,https://another-site.org" \
  -e EMBETTY_CACHE="redis://your-redis-host:6379" \
  -e TWITTER_BEARER_TOKEN="YOUR_TWITTER_BEARER_TOKEN" \
  heiseonline/embetty-server:latest

Command Breakdown:

  • -d: Run the container in detached mode (in the background).
  • -p 8080:8080: Map port 8080 on the host to port 8080 in the container.
  • --name embetty-server: Assign a name to the container for easy management.
  • --restart always: Automatically restart the container if it stops.
  • -e ...: Set environment variables for configuration. See the Configuration page for a full list.

Behind a Reverse Proxy

In a production environment, you should run Embetty behind a reverse proxy like Nginx or Traefik. The reverse proxy can handle SSL termination, caching, and routing requests to the Embetty container.

Example Nginx configuration snippet:

location /embetty/ {
    proxy_pass http://127.0.0.1:8080/;
    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;
}

If you use a setup like this, you should also set the URL_BASE environment variable to match the public URL:

-e URL_BASE="https://your-website.com/embetty"

Dockerfile Analysis

The project's Dockerfile uses a multi-stage build to create a small and optimized production image.

FROM node:lts-alpine as builder
WORKDIR /build
COPY . .
RUN corepack enable \
  && pnpm i --frozen-lockfile \
  && pnpm build \
  && pnpm --filter server --prod deploy .target

FROM node:lts-alpine

ENV TZ=Europe/Berlin
ENV LC_ALL=de_DE.UTF-8
ENV NODE_ENV=production
ENV PORT 8080
ENV NODE_OPTIONS="--max-old-space-size=500 --no-experimental-fetch --dns-result-order=ipv4first"

WORKDIR /app
USER nobody

COPY --chown=nobody:nobody --from=builder /build/.target /app

CMD node dist/server.js
  • Stage 1 (builder): Installs all dependencies (including dev), builds the project, and then uses pnpm deploy to create a clean production-only node_modules directory in .target.
  • Stage 2 (Final Image): Starts from a fresh node:lts-alpine image, sets production environment variables, creates a non-root user (nobody), copies only the built application files from the builder stage, and sets the CMD to run the server.

This process ensures the final image does not contain build tools, development dependencies, or source code, making it smaller and more secure.