Linux things 🐧

un blog sur les technologies des logiciels libres et autres digressions


WebDAV : un serveur léger en Go

usage d'un serveur WebDAV avec Enpass

Wed, 08 Jan 2025 21:20:30 +0200
# webdav   # enpass   # auto-hebergement   # nomad  

Introduction

J’affectionne le protocole S3 pour mes sauvegardes et stocker les donnĂ©es d’applications compatibles S3. Cependant un vieux protocole crĂ©Ă© en 1996 est encore grandement utilisĂ© par des applications comme Nextcloud.

WebDAV est ce protocole qui permet de gĂ©rer ses fichiers vers un serveur afin d’en ajouter, les modifier ou les supprimer. Il est basĂ© sur HTTP et permet les accĂšs concurrents vers la mĂȘme ressource.
Par exemple Nexcloud intĂšgre un serveur WebDAV, ainsi l’agent de synchronisation Nextcloud installĂ© sur les postes de travail peut mettre Ă  jour les fichiers de l’utilisateur ou d’un groupe d’utilisateurs vers le serveur.

Enpass

Depuis quelques temps j’ai dĂ©cidĂ© de revenir vers Enpass car il n’impose pas de Cloud. Voir mon article sur les gestionnaires de mots de passe.

Je suis actuellement dans une démarche auto-hébergement grùce à ma stack basée sur Nomad / Docker / Tricot / Tailscale qui me facilite la mise en place de nouveaux outils. De plus mon infra de backup basée sur un S3 local dans un RAID 1 est plutÎt rassurante.

Enpass propose une synchronisation locale en WIFI. C’est pratique car cela permet de synchroniser l’application desktop avec la version mobile lorsqu’on rentre chez soi. Cependant on ne peut pas choisir l’IP du serveur de synchro embarquĂ© dans le client de bureau. J’aurais souhaitĂ© lui faire utiliser l’IP Tailscale plutĂŽt que celle en 192.168.X.X.

WebDAV

Enpass supporte ce protocole, mais je ne voulais pas installer et gérer une usine à gaz juste pour synchroniser mes mots de passe. Jusquà ce que je tombe sur ce bijou : webdav : A simple and standalone WebDAV server.

webdav est un serveur lĂ©ger en Go et trĂšs simple Ă  configurer. Il peut gĂ©rer plusieurs comptes utilisateurs ce qui est nĂ©cessaire lorqu’on a plusieurs coffres dans son Enpass (il faut un compte par coffre).

Nomad

Voici la configuration Nomad du service auto-hébergé.

webdav.hcl

job "webdav" {
  datacenters = ["dc1"]
  type        = "service"

  group "home" {
    count = 1

    network {
      port "http" {
        to           = 6060 # container port the app runs on
        host_network = "tailscale"
      }
    }

    task "webdav" {
      driver = "docker"

      constraint {
        attribute = "${attr.unique.hostname}"
        value     = "nuc"
      }


      config {
        image = "hacdias/webdav"

        mounts = [
          {
            type     = "bind"
            target   = "/data"
            source   = "/data/volumes/webdav/data"
            readonly = false
            bind_options = {
              propagation = "rshared"
            }
          },
          {
            type     = "bind"
            target   = "/config.yml"
            source   = "/data/volumes/webdav/config.yml"
            readonly = true
            bind_options = {
              propagation = "rshared"
            }
          }
        ]
        ports = ["http"]
      }

      resources {
        cpu    = 100
        memory = 200
      }

      service {
        name     = "webdav"
        provider = "consul"
        port     = "http"

        tags = ["tricot webdav.domain.tld"]

      }
    }
  }
}

Et la configuration yaml de l’outil

config.yml

address: 0.0.0.0
port: 6060

# TLS-related settings if you want to enable TLS directly.
tls: false
cert: cert.pem
key: key.pem

# Prefix to apply to the WebDAV path-ing. Default is '/'.
prefix: /

# Enable or disable debug logging. Default is 'false'.
debug: false

# Disable sniffing the files to detect their content type. Default is 'false'.
noSniff: false

# Whether the server runs behind a trusted proxy or not. When this is true,
# the header X-Forwarded-For will be used for logging the remote addresses
# of logging attempts (if available).
behindProxy: true

# The directory that will be able to be accessed by the users when connecting.
# This directory will be used by users unless they have their own 'directory' defined.
# Default is '.' (current directory).
# directory: .
# directory: /data/volumes/webdav/data/

# The default permissions for users. This is a case insensitive option. Possible
# permissions: C (Create), R (Read), U (Update), D (Delete). You can combine multiple
# permissions. For example, to allow to read and create, set "RC". Default is "R".
permissions: CRUD

# The default permissions rules for users. Default is none. Rules are applied
# from last to first, that is, the first rule that matches the request, starting
# from the end, will be applied to the request.
rules: []

# The behavior of redefining the rules for users. It can be:
# - overwrite: when a user has rules defined, these will overwrite any global
#   rules already defined. That is, the global rules are not applicable to the
#   user.
# - append: when a user has rules defined, these will be appended to the global
#   rules already defined. That is, for this user, their own specific rules will
#   be checked first, and then the global rules.
# Default is 'overwrite'.
rulesBehavior: overwrite

# Logging configuration
log:
  # Logging format ('console', 'json'). Default is 'console'.
  format: console
  # Enable or disable colors. Default is 'true'. Only applied if format is 'console'.
  colors: true
  # Logging outputs. You can have more than one output. Default is only 'stderr'.
  outputs:
  - stderr

# CORS configuration
cors:
  # Whether or not CORS configuration should be applied. Default is 'false'.
  enabled: false
  credentials: true
  allowed_headers:
    - Depth
  allowed_hosts:
    - http://IP_TAILSCALE_NUC:6060
  allowed_methods:
    - GET
  exposed_headers:
    - Content-Length
    - Content-Range

# The list of users. If the list is empty, then there will be no authentication.
# Otherwise, basic authentication will automatically be configured.
#
# If you're delegating the authentication to a different service, you can proxy
# the username using basic authentication, and then disable webdav's password
# check using the option:
#
# noPassword: true
users:
  - username: user
    password: "{bcrypt}PASS_CHIFFRE"
    directory: /data/vault_master
  - username: user2
    password: "{bcrypt}PASS_CHIFFRE"
    directory: /data/vault_autre

le pass chiffré est généré avec la commande ./webdav bcrypt 'PASS'. Il suffit de télécharger le binaire selon sa plateforme.

Une fois le job lancĂ© Tricot va gĂ©nĂ©rer un certificat Let’s Encrypt et reverse https://webdav.domain.tld vers le NUC.

Il n’y a plus qu’Ă  ajouter le service WebDAV dans le coffre de son Enpass sur chaque device et enjoy !

Systemd

Si l’on a pas besoin d’un service publique, ni de Docker, Systemd peut facilement lancer webdav en local.

/data/volumes/webdav/config.yml

address: IP_LOCALE
port: 6060

# TLS-related settings if you want to enable TLS directly.
tls: false
cert: cert.pem
key: key.pem

# Prefix to apply to the WebDAV path-ing. Default is '/'.
prefix: /

# Enable or disable debug logging. Default is 'false'.
debug: false

# Disable sniffing the files to detect their content type. Default is 'false'.
noSniff: false

# Whether the server runs behind a trusted proxy or not. When this is true,
# the header X-Forwarded-For will be used for logging the remote addresses
# of logging attempts (if available).
behindProxy: false

# The directory that will be able to be accessed by the users when connecting.
# This directory will be used by users unless they have their own 'directory' defined.
# Default is '.' (current directory).
# directory: .
directory: /data/volumes/webdav/data/

# The default permissions for users. This is a case insensitive option. Possible
# permissions: C (Create), R (Read), U (Update), D (Delete). You can combine multiple
# permissions. For example, to allow to read and create, set "RC". Default is "R".
permissions: CRUD

# The default permissions rules for users. Default is none. Rules are applied
# from last to first, that is, the first rule that matches the request, starting
# from the end, will be applied to the request.
rules: []

# The behavior of redefining the rules for users. It can be:
# - overwrite: when a user has rules defined, these will overwrite any global
#   rules already defined. That is, the global rules are not applicable to the
#   user.
# - append: when a user has rules defined, these will be appended to the global
#   rules already defined. That is, for this user, their own specific rules will
#   be checked first, and then the global rules.
# Default is 'overwrite'.
rulesBehavior: overwrite

# Logging configuration
log:
  # Logging format ('console', 'json'). Default is 'console'.
  format: console
  # Enable or disable colors. Default is 'true'. Only applied if format is 'console'.
  colors: true
  # Logging outputs. You can have more than one output. Default is only 'stderr'.
  outputs:
  - stderr

# CORS configuration
cors:
  # Whether or not CORS configuration should be applied. Default is 'false'.
  enabled: false
  credentials: true
  allowed_headers:
    - Depth
  allowed_hosts:
    - http://IP_LOCALE:6060
  allowed_methods:
    - GET
  exposed_headers:
    - Content-Length
    - Content-Range

# The list of users. If the list is empty, then there will be no authentication.
# Otherwise, basic authentication will automatically be configured.
#
# If you're delegating the authentication to a different service, you can proxy
# the username using basic authentication, and then disable webdav's password
# check using the option:
#
# noPassword: true
users:
  - username: user
    password: "{bcrypt}PASS_CHIFFRE"
    directory: /data/volumes/webdav/data/vault_master
  - username: user2
    password: "{bcrypt}PASS_CHIFFRE"
    directory: /data/volumes/webdav/data/vault_autre

Copier le binaire webdav dans /usr/local/bin et créer le service

/etc/systemd/system/webdav.service

[Unit]
Description=WebDAV
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/webdav --config /data/volumes/webdav/config.yml
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now webdav

Le service ne sera accessible que dans votre réseau local ou par Tailscale si vous remplacez IP_LOCALE par IP_TAILSCALE_NUC.

Conclusion

Le grand intĂ©rĂȘt d’avoir un serveur WebDAV, plutĂŽt qu’un backend dĂ©diĂ© type vaultwarden, est qu’il peut aussi servir pour d’autres applications đŸ€™

(Ce texte a été écrit avec VNote)