The server is configured with a config.yaml file (the path is passed with the --config flag). Settings are applied at startup — changes require a server restart. Entities (repositories, users, roles) are not described in the file — they are managed through the web interface.

The list of all parameters with their defaults is in Configuration parameters.

Value formats

Durations and sizes are written the same way in the file and in the environment variables:

  • a duration is a string with a unit of measurement: s for seconds, m for minutes, h for hours; composite values (1h30m) are allowed. A number without a unit of measurement is rejected at startup;
  • a size is a string with a unit of measurement: K, M, G, T (or KB, MB, GB, TB); the multipliers are binary, so 256K is 262,144 bytes. A number without a unit of measurement means bytes, and 0 removes the limit.

Environment variables

Any file key can be overridden with a GALLEON_* variable: dots become underscores, database.hostGALLEON_DATABASE_HOST, gc.grace_periodGALLEON_GC_GRACE_PERIOD.

Rules:

  • an environment variable takes precedence over the file value;
  • lists are comma-separated: GALLEON_SERVER_MONITORING_ALLOWLIST="127.0.0.0/8,::1/128";
  • do not leave empty parent blocks in the file (for example, a bare security: with no keys) — they may prevent nested environment variables from applying.

Mandatory parameters

The following keys have no defaults — the server does not start without them:

  • database.user and database.dbname — the database credentials;
  • storage.default.type and the storage path for the chosen type;
  • security.secret_key_file — the path to the encryption key file;
  • auth.bootstrap_admin — only on the first start with an empty database.

What is configured where

The parameters are grouped into blocks:

BlockWhat it configures
serverThe address and port, request limits, reverse proxy trust, access to the health endpoints
databaseThe PostgreSQL connection and connection pool sizes
storageThe type and root directory of the artifact file storage
securityThe path to the encryption key file
authThe first administrator, the verified credential cache, session lifetimes
ociTimeouts for pulling container images from external registries
gcThe schedule and parameters of storage garbage collection
indexBackground building of the service repository indexes
loggingThe level, format, and sources of log records
proxyProtection of the outbound requests of proxy repositories

Typical tasks

Cap the artifact upload size

Galleon has no limit of its own by default (server.max_upload_size: 0). If a reverse proxy stands in front of the server, keep its request body size in sync with this one (Reverse proxy).

To set the limit on the Galleon side:

server:
  max_upload_size: 10GB

Exceeding it reaches the client as a 413 error.

Enable a TLS connection to the database

The certificate validation mode is set by the database.sslmode key:

database:
  sslmode: verify-full

The values match the PostgreSQL modes: require encrypts the connection, verify-ca and verify-full also validate the certificate.

Collect verbose logs for diagnostics

Two keys of the logging block raise the log verbosity:

logging:
  level: debug
  registry_level: info

The first key raises the verbosity of the Galleon logs, the second — of the records about container image operations; it is needed when investigating image problems. Restore the previous values after the diagnostics: at the debug level the record volume is much higher.

Allow proxying into an internal network

Requests from proxy repositories to private IP addresses are forbidden by default: loopback, the RFC 1918 ranges (10/8, 172.16/12, 192.168/16), link-local, CGNAT (100.64/10), multicast, broadcast, and IPv6 ULA. The ban is checked when the repository is saved (against the addresses the external registry name resolves to), on every connection, and on redirects: the address from the Location header goes through the same check.

To allow a specific internal address:

proxy:
  ssrf:
    allowlist:
      ips:
        - 10.0.0.10
      domains:
        - registry.internal.example.com

The exception list accepts both IP addresses and host names; a name is matched in full, so subdomains are not covered by the exception. Private addresses outside the list stay blocked. The metadata service addresses of cloud providers (for example, 169.254.169.254) are blocked always — they cannot be put on the exception list.

Grow the connection pools under load

Grow the pools if the database connections stopped being enough under load. Connections are taken by parallel builds, by the background index building, and especially by proxying container images: while a layer is being fetched from the external registry it keeps a connection (up to two per docker pull).

The signs of a shortage:

  • requests respond slowly while the database itself is not loaded: there are few active queries in pg_stat_activity, but the number of Galleon connections sits at max_open_conns — meaning requests are queuing for a free connection;
  • the database itself is out of slots: PostgreSQL stops accepting new connections, requests fail, and the access log starts carrying the sqlstate field with a class 53 code — resource exhaustion (see Logging).

The pool usage is visible in PostgreSQL:

SELECT application_name, count(*) FROM pg_stat_activity GROUP BY 1 ORDER BY 2 DESC;

The galleon label is the main pool, galleon-oci-meta is the image metadata read pool; the connections serving container images carry no label.

database:
  max_open_conns: 80
  registry_max_open_conns: 40

The defaults are 40 and 25. After the change, recalculate the database max_connections. Galleon connects to it with three pools: two are capped by max_open_conns (hence the doubling in the formula), the third by registry_max_open_conns. PostgreSQL also keeps a few connections in reserve for the superuser (superuser_reserved_connections, 3 by default):

max_connections >= max_open_conns × 2 + registry_max_open_conns + superuser_reserved_connections

At the defaults that is 40 + 40 + 25 + 3 = 108, so for a production installation set it to at least 110. Leave a few spare slots for psql and one-off operations.