From a6f2ac1ee7400bed06f37df2262eab941dee1d12 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Sat, 21 Feb 2026 15:00:11 +1300 Subject: [PATCH] Dockerfile for chorus (may need tweaking still) --- docker/.gitignore | 1 + docker/Dockerfile | 39 +++++ docker/README.md | 6 + docker/chorus.toml.in | 354 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 docker/.gitignore create mode 100644 docker/Dockerfile create mode 100644 docker/README.md create mode 100644 docker/chorus.toml.in diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 0000000..e22ec51 --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1 @@ +/chorus.toml diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..a7aefa8 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,39 @@ +FROM alpine:latest + +# Install system packages +RUN apk add --no-cache curl gcc musl-dev openssl-dev pkgconfig git make cmake + +# Install rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +# Setup chorus user and directories +RUN adduser --system --home /opt/chorus --shell /bin/sh chorus && \ + mkdir -p /opt/chorus/etc /opt/chorus/src /opt/chorus/var /opt/chorus/sbin /opt/chorus/lib && \ + mkdir -p /opt/chorus/var/chorus /opt/chorus/var/www && \ + mkdir -p /opt/chorus/lib/systemd/system && \ + chown -R chorus /opt/chorus + +# Clone chorus +WORKDIR /opt/chorus/src +RUN git clone https://github.com/mikedilger/chorus + +# Build chorus +WORKDIR /opt/chorus/src/chorus +RUN git checkout latest && ~/.cargo/bin/cargo build --release +RUN install --mode=0700 --owner=chorus -t /opt/chorus/sbin/ \ + ./target/release/chorus \ + ./target/release/chorus_compress \ + ./target/release/chorus_dump \ + ./target/release/chorus_dump_approvals \ + ./target/release/chorus_moderate \ + ./target/release/chorus_cmd + +COPY chorus.toml /opt/chorus/etc/chorus.toml +RUN chown chorus /opt/chorus/etc/chorus.toml + +WORKDIR /opt/chorus +USER chorus +ENV RUST_BACKTRACE=1 +ENV RUST_LOG=info + +ENTRYPOINT ["/opt/chorus/sbin/chorus", "/opt/chorus/etc/chorus.toml"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..be7eaf5 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,6 @@ +# Docker install of Chorus + +You need to `cp chorus.toml.in chorus.toml` and then edit this file +to set up your configuration + +Then you can build the container: `docker build .` diff --git a/docker/chorus.toml.in b/docker/chorus.toml.in new file mode 100644 index 0000000..00d983d --- /dev/null +++ b/docker/chorus.toml.in @@ -0,0 +1,354 @@ +# This is a config file for the Chorus nostr relay +# Refer to https://github.com/mikedilger/chorus + +# This is the directory where chorus stores data. +# +# Default is "/tmp". +# +# If deployed according to docs/DEPLOYING.md, is "/opt/chorus/var/chorus". +# +data_directory = "/opt/chorus/var/chorus" + + +# This is the IP address that chorus listens on. If deployed directly on the +# Internet, this should be an Internet globally accessible IP address. +# If proxied or if testing locally, this can be a localhost address. +# +# Default is "127.0.0.1". +# +ip_address = "0.0.0.0" + + +# This is the port that chorus listens on. If deployed directly on the Internet, +# this should probably be 443 which is the expected default port for the +# "wss://" protocol. +# +# Default is 443. +# +port = 443 + + +# This is the DNS hostname of your relay. +# This is used for verifying AUTH events, which specify your relay host name. +# +hostname = "localhost" + + +# If chorus is behind a proxy like nginx, set this to true. In this case chorus will look for and +# trust the `X-Real-Ip` HTTP request header to get the real IP of the client. This header MUST exist +# or the connection will not be served. +# +# Default is false. +# +chorus_is_behind_a_proxy = true + + +# If chorus is behing a proxy, it can't compute it's Internet-visible URL. So set it here. +# This is used currently by web management and blossom and maybe more in the future. +# +# Default is not set. +# +# base_url = + +# If true, chorus will handle TLS, running over HTTPS. If false, chorus run over HTTP. +# +# If you are proxying via nginx, normally you will set this to false and allow nginx to handle TLS. +# +use_tls = false + + +# This is the path to your TLS certificate chain file. +# +# If use_tls is false, this value is irrelevant. +# +# Default is "./tls/fullchain.pem". +# +# If deployed according to docs/DEPLOYING.md using the direct method, this is set to +# "/opt/chorus/etc/tls/fullchain.pem" and the systemd service copies letsencrypt TLS +# certificates into this position on start. +# +certchain_pem_path = "/use/an/nginx/proxy" + + +# This is the path to yoru TLS private key file. +# +# If use_tls is false, this value is irrelevant. +# +# Default is "./tls/privkey.pem". +# +# If deployed according to docs/DEPLOYING.md using the direct method, this is set to +# "/opt/chorus/etc/tls/privkey.pem" and the systemd service copies letsencrypt TLS +# certificates into this position on start. +# +key_pem_path = "/use/an/nginx/proxy" + + +# This is a name for your relay, displayed in the NIP-11 response. +# +# Default is "Chorus Default" +# +# name = "Chorus Default" + + +# This is a description for your relay, displayed in the NIP-11 response. +# +# Default is "A default config of the Chorus relay" +# +# description = "A default config of the Chorus relay" + + +# This is a banner URL pointing to an image representing your relay, displayed in the NIP-11 +# response. +# +# Default is not set +# +# banner_url = + + +# This is an icon URL pointing to an image representing your relay, displayed in the NIP-11 +# response. +# +# Default is not set +# +# icon_url = + + +# This is an optional privacy policy as a blob of text (not a URL, not HTML). +# +# Default is not set +# +# privacy_policy = "" + + +# This is an optional terms of service document as a blob of text (not a URL, not HTML). +# +# Default is not set +# +# terms_of_service = "" + + +# This is an optional contact for your relay, displayed in the NIP-11 response. +# +# Default is not set +# +# contact = + + +# This is an optional public key (hex format) for your relay, displayed in the NIP-11 response. +# +# Default is not set +# +# contact_public_key_hex = + + +# If open_relay is true, the relay behaves as an open public relay. +# +# Default is false. +# +# open_relay = false + + +# These are the public keys (hex format) of your relay's administrators. This does NOT +# automatically make them a relay user, but it will eventually allow them to add/remove users +# and moderators. +# +# Default is [] +# +admin_hex_keys = [] + + +# This is a boolean indicating whether or not chorus verifies incoming events. +# +# This setting only skips verification of events that are submitted by AUTHed and +# authorized users. Chorus always verifies incoming AUTH events, and any event that +# is not submitted by an AUTHed and authorized relay user. +# +# Default is true. +# +verify_events = true + + +# This is a boolean indicating whether or not scraping is allowed. Scraping is any filter +# where all of the following are true: +# +# - `ids` is missing or empty +# - `authors` is missing or empty +# - There are no `#X` tag filters +# +# Filter that fail to match these conditions will be rejected if allow_scraping is false. +# +# If allow_scraping is true, be aware that filters that don't match any of these conditions +# (and are not bound by since/until/limit) have no indexes to speed up their query, so they +# scan through every single event on the relay. +# +# See also `allow_scrape_if_limited_to` and `allow_scrape_if_max_seconds`. +# +# Default is false. +# +allow_scraping = false + + +# This is a u32 count of events indicating a filter `limit` value under which a scrape is +# allowed, irrespective of the `allow_scraping` setting. Such scrapes are not expensive due +# to the limit. The limit must be specified in the filter; it does not do the scrape and +# then count to see if it was under the limit. +# +# See `allow_scraping` to learn the definition of a scrape. +# +# The default is 100. +# +allow_scrape_if_limited_to = 500 + + +# This is a u64 number of seconds indicating a filter time range under which a scrape is +# allowed, irrespective of the `allow_scraping` setting. Such scrapes are rarely expensive +# due to the short time period. +# +# See `allow_scraping` to learn the definition of a scrape. +# +# The default is 7200. +# +allow_scrape_if_max_seconds = 14400 + + +# Within negentropy synchronization, allow scraping +# +# The default is true +# +allow_scrape_if_negentropy = true + + +# This is an integer indicating the maximum number of subscriptions a connection can have open +# at a given time. +# +# If you set this too low, clients will be incentivised to resubmit updated subscriptions which +# will pull down the same events over again, instead of submitting a new subscription that only +# gets the additional events that the client wants. It may seem intuitive that setting this to +# a low value like 10 will decrease server load, but it will probably increase server load. +# +# It is strongly recommended to not go below 16. +# +# Default is 128. +# +max_subscriptions = 128 + + +# Whether or not to accept and serve all ephemeral events to everybody. +# +# Default is true. +# +serve_ephemeral = true + +# Whether or not to accept and serve kind 10002 Relay List Metadata (NIP-65) events to everybody. +# +# Default is true. +# +serve_relay_lists = true + +# How verbose to log issues with the main server code. +# +# Possible values are: Trace, Debug, Info, Warn, Error +# +# Default is Info +# +server_log_level = "Info" + + +# How verbose to log library issues and other general issues +# +# Possible values are: Trace, Debug, Info, Warn, Error +# +# Default is Info +# +library_log_level = "Info" + + +# How verbose to log issues with client requests +# +# Possible values are: Trace, Debug, Info, Warn, Error +# +# Default is Info +# +client_log_level = "Info" + + +# Whether to block incoming connections based on recent prior behavior +# +# Chorus normally blocks IP addresses for a short period preventing quick reconnections, +# and for a longer period if the previous connection ended in some error condition. +# +# By setting this variable to false, it will allow all connections, incluing poorly behaving +# clients that reconnect over and over in a tight loop. +# +# Default is true +# +enable_ip_blocking = true + + +# Number of seconds to ban an IP address after disconnection. +# +# Enforcing this minimum ban prevents clients from immediately reconnecting which can cause tight loops. +# Only relevant if enable_ip_blocking is true. +# +# Default is 1 +# +minimum_ban_seconds = 1 + + +# Number of seconds beyond which chorus times out a client that has no open subscriptions. +# +# Default is 60 +# +timeout_seconds = 60 + + +# Maximum number of websocket connections per IP address +# +# Default is 5 +# +max_connections_per_ip = 5 + + +# The maximum rate (excluding bursts) of data that will be transmitted over a websocket connection +# (both directions, per connection). Beyond this rate (in a sustained way) the connection will be +# closed. +# +# Default is 1024576 bytes per second. +# +throttling_bytes_per_second = 1024576 + + +# The allowable bursts of data beyond the normal rate. +# +# We keep a count of how many bytes they are allowed, and that count starts at this number. +# As bytes are consumed the count goes down, but we refund throttling_bytes_per_second every +# second. If that bucket doesn't have enough, the burst won't be allowed and the connection +# will be closed. +# +# Default is 16777216 bytes. +# +throttling_burst = 16777216 + + +# Blossom server directory +# +# Set to a filesystem directory where you want chorus to store files. +# +# Blossom allows clients to upload files making them available for the public to download. +# Our implementation makes all files publicly readable, but only chorus users can upload +# or delete. See https://github.com/hzrd149/blossom +# +# Default is not set +# +# blossom_directory = + + +# Whether to allow negentropy syncing or not +# +# If this is enabled, keep in mind that some negentropy syncs are scrapes and if you want to +# allow those, you should also enable allow_scraping. But this will require scans of the entire +# database since scrapes have no indexes. +# +# Default is false +# +enable_negentropy = false