Skip to content

Server

The server section defines network listeners, HTTP routers, TCP routers, middleware, and TLS certificates.

yaml
server:
  load_value: ""
  entrypoints:
    web:
      address: ":8080"
      network: tcp
  http:
    tls:
      store: {}
    middlewares: {}
    routers: {}
  tcp:
    middlewares: {}
    routers: {}

Entrypoints

Entrypoints are named listeners. Routers attach to one or more entrypoints.

yaml
server:
  entrypoints:
    web:
      address: ":8080"
      network: tcp
    docker:
      address: ":2375"
      network: tcp
FieldDefaultDescription
addressAddress passed to net.Listen, such as :8080 or /var/run/app.sock.
networktcpNetwork passed to net.Listen. Use udp, udp4, or udp6 for a UDP entrypoint, which is bound with net.ListenPacket and consumed by server.udp routers.

HTTP Routers

HTTP routers match a host, path, and entrypoint, then run an ordered middleware chain.

yaml
server:
  http:
    routers:
      app:
        host: example.com
        path:
          - /api/*
        entrypoints:
          - web
        middlewares:
          - strip_api
          - app_service
        tls: {}
        pre_middlewares:
          request_id: true
          server_info: true
FieldDescription
hostOptional host rule. The port is stripped before matching. Empty host acts as a fallback for the entrypoint.
pathOne or more chi route patterns.
entrypointsListener names. Defaults to all listeners.
middlewaresOrdered middleware names from server.http.middlewares.
tlsEnable TLS on this router when present.
pre_middlewares.request_idEnable built-in request ID middleware. Default is true.
pre_middlewares.server_infoEnable built-in Server response header. Default is true.

Each router always includes panic recovery, Turna request context setup, optional pre-middlewares, configured middlewares, and a final 204 No Content fallback.

HTTP Middlewares

Declare middleware instances under server.http.middlewares, then reference their names from routers.

yaml
server:
  http:
    middlewares:
      strip_api:
        strip_prefix:
          prefix: /api
      app_service:
        service:
          loadbalancer:
            servers:
              - url: http://localhost:3000
    routers:
      app:
        path: /api/*
        middlewares:
          - strip_api
          - app_service

A single named middleware object uses the first configured middleware type in the registry. Do not put multiple middleware types under one middleware name; create separate named middleware entries and chain them in the router.

See the HTTP middleware index for all supported keys.

TLS

Add tls: {} to a router to serve that router over TLS. Do not mix TLS and non-TLS routers on the same entrypoint.

yaml
server:
  entrypoints:
    websecure:
      address: ":8443"
  http:
    tls:
      min_version: "1.3"
      store:
        default:
          - cert_file: ./cert.pem
            key_file: ./key.pem
        app.example.com:
          - cert_file: ./app.pem
            key_file: ./app-key.pem
        "*.internal.example.com":
          - cert_file: ./internal.pem
            key_file: ./internal-key.pem
    routers:
      secure:
        entrypoints:
          - websecure
        path: /*
        tls: {}
        middlewares:
          - app
FieldDefaultDescription
min_version1.3Minimum accepted TLS version: 1.2 or 1.3.
store.<host>Certificate(s) served for the SNI host name <host>.
store.defaultFallback certificate used when no SNI host matches or the client sends no SNI.
self_signedCustomizes the generated certificate (see below).
acmeAutomatic certificate provisioning from an ACME CA such as Let's Encrypt (see below).

SNI (multiple certificates)

store keys are SNI host names. On each TLS handshake the certificate is selected by the client's SNI server name:

  1. exact host match (e.g. app.example.com),
  2. wildcard match by replacing the first label (e.g. api.internal.example.com matches *.internal.example.com),
  3. an ACME-provisioned certificate when acme is enabled and the host is allowed,
  4. the default host key,
  5. a generated self-signed certificate when nothing else matches.

ACME (Let's Encrypt)

Enable acme to automatically obtain and renew certificates from an ACME CA (Let's Encrypt by default) using the TLS-ALPN-01 challenge. The challenge is answered over the existing TLS entrypoint, so no extra HTTP port is required, but the TLS entrypoint (usually :443) must be reachable from the public internet for validation to succeed.

yaml
server:
  entrypoints:
    websecure:
      address: ":443"
  http:
    tls:
      acme:
        enabled: true
        email: admin@example.com
        domains:
          - app.example.com
        cache_dir: ./acme-cache
        # Use the staging CA while testing to avoid rate limits.
        directory_url: "https://acme-staging-v02.api.letsencrypt.org/directory"
    routers:
      secure:
        entrypoints:
          - websecure
        path: /*
        tls: {}
        middlewares:
          - app
FieldDefaultDescription
enabledfalseTurns on ACME certificate provisioning.
emailContact address registered with the ACME account.
domainsAllow-list of host names certificates may be issued for. A request for a host outside this list is rejected.
cache_diracme-cacheDirectory used to persist the account key and issued certificates.
directory_urlLet's Encrypt productionACME directory endpoint. Leave empty for the Let's Encrypt production CA, or set the staging URL while testing.

Certificates are issued on first request and renewed automatically. Use the Let's Encrypt staging directory (https://acme-staging-v02.api.letsencrypt.org/directory) during testing; the production CA enforces strict rate limits. Wildcard certificates are not supported by the TLS-ALPN-01 challenge — list each host explicitly under domains. Entries configured in store still take precedence for their exact/wildcard host names.

Self-signed certificate

If no certificate is configured for a matched host, Turna generates a self-signed certificate. By default it is valid for localhost, 127.0.0.1, and ::1. Extend it with self_signed:

yaml
server:
  http:
    tls:
      self_signed:
        organization:
          - turna
        dns_names:
          - dev.local
        ips:
          - 192.168.1.10

TCP Routers

TCP routers attach TCP middleware chains to TCP entrypoints.

yaml
server:
  entrypoints:
    docker:
      address: ":2375"
  tcp:
    middlewares:
      local_only:
        ip_allow_list:
          source_range:
            - 127.0.0.1/32
      docker_socket:
        redirect:
          address: /var/run/docker.sock
          network: unix
    routers:
      docker:
        entrypoints:
          - docker
        middlewares:
          - local_only
          - docker_socket

TCP middleware runs sequentially for each accepted connection. If a middleware returns an error, the chain stops and the connection is closed.

UDP Routers

UDP routers attach UDP middleware chains to UDP entrypoints (network: udp). UDP is connectionless, so the chain runs per received datagram instead of per connection.

yaml
server:
  entrypoints:
    dns:
      address: ":5353"
      network: udp
  udp:
    middlewares:
      local_only:
        ip_allow_list:
          source_range:
            - 127.0.0.1/32
      resolver:
        dns:
          origin: example.com
          records:
            - "@ IN A 10.0.0.1"
            - "www IN A 10.0.0.2"
            - "*.dev IN A 10.0.0.9"
          upstream:
            - 1.1.1.1:53
    routers:
      dns:
        entrypoints:
          - dns
        middlewares:
          - local_only
          - resolver

UDP middleware runs sequentially for each datagram. A pre-filter such as ip_allow_list returns an error to drop the packet; a terminal middleware such as dns or redirect writes the response back to the peer. Datagrams are handled concurrently with a bounded worker pool.

See the UDP middleware references for dns, ip_allow_list, and redirect.