Giter VIP home page Giter VIP logo

caddy-ansible's Introduction

Caddy Ansible Role

This role installs and configures the caddy web server. The user can specify any http configuration parameters they wish to apply their site. Any number of sites can be added with configurations of your choice.

Dependencies

None

Role Variables

The Caddyfile

See Caddyfile docs. Notice the | used to include a multi-line string. You may set caddy_conf_filename to config.json to use json format.

default:

caddy_conf_filename: Caddyfile
caddy_config: |
  http://localhost:2020
  respond "Hello, world!"

If you wish to use a template for the config you can do this:

caddy_config: "{{ lookup('template', 'templates/Caddyfile.j2') }}"

Whether to template the Caddyfile on each run

By default the Caddyfile is templated on each run. By setting this variable you can ensure the file is created on the first run but never updated after.

caddy_config_update: true

The OS to download caddy for

default:

caddy_os: linux

The version of Caddy to use

default:

caddy_version: ''

This option cannot be used together with caddy_packages because that option prevents the downloads from using Github, meaning no older versions are available.

The version of Caddy will only be changed after the first run of the role if caddy_update is set to true, otherwise the version of Caddy will remain as the one selected on first run of the role.

Auto update Caddy?

default:

caddy_update: true

Additional Available Packages

Changing this variable will reinstall Caddy with the new packages if caddy_update is enabled. Check https://caddyserver.com/download for available packages.

This causes the builds to be downloaded from https://caddyserver.com rather than using the github releases. This service is provided for free by the Caddy maintainers and if you rely on it you should consider donating. The capacity of this service is limited so if you use this role to manage Caddy across many hosts it is recommended to use a different method.

default:

caddy_packages: []

Use setcap?

This allows Caddy to open a low port (under 1024 - e.g. 80, 443).

default:

caddy_setcap: true

Use systemd capabilities controls

default:

caddy_systemd_capabilities_enabled: false
caddy_systemd_capabilities: "CAP_NET_BIND_SERVICE"

NOTE: This feature requires systemd v229 or newer and might be needed in addition to caddy_setcap: yes.

Supported:

  • Debian 9 (stretch)
  • Fedora 25
  • Ubuntu 16.04 (xenial)

RHEL/CentOS has no release that supports systemd capability controls at this time.

Add additional environment variables or files

Add environment variables to the systemd script.

default:

caddy_environment_variables: {}

Example usage:

caddy_environment_variables:
  FOO: bar
  SECONDVAR: spam

Add environment files to the systemd script.

default:

caddy_environment_files: []

Example usage:

caddy_environment_files:
  - /etc/default/caddy_additional_env_file

Use additional CLI arguments

default:

caddy_additional_args: ""

Example for LetsEncrypt staging:

caddy_additional_args: "-ca https://acme-staging.api.letsencrypt.org/directory"

Use a GitHub OAuth token to request the list of caddy releases

This role uses the GitHub releases list to check when a new version is available. GitHub has some fairly agressive rate-limiting which can cause failures. You can set your GitHub token to increase the limits for yourself when running the role (e.g. if deploying many servers behind a NAT or running this role repeatedly as part of a CI process).

default:

caddy_github_token: ""

Example Playbooks

---
- hosts: all
  become: yes
  roles:
    - role: caddy_ansible.caddy_ansible
      caddy_config: |
        files.example.com
        encode gzip
        file_server browse {
            root /home/caddy/
        }

Example with DigitalOcean DNS for TLS:

---
- hosts: all
  roles:
    - role: caddy_ansible.caddy_ansible
      caddy_environment_variables:
        DO_AUTH_TOKEN: "your-token-here"
      caddy_systemd_capabilities_enabled: true
      caddy_systemd_network_dependency: false
      caddy_packages: ["github.com/caddy-dns/lego-deprecated"]
      caddy_config: |
        nextcloud.example.com {
            log

            reverse_proxy http://localhost:8080 {
                header_up Host {http.request.host}
                header_up X-Real-IP {http.request.remote.host}
                header_up X-Forwarded-For {http.request.remote.host}
                header_up X-Forwarded-Port {http.request.port}
                header_up X-Forwarded-Proto {http.request.scheme}
            }

            tls [email protected] {
                dns lego_deprecated digitalocean
            }
        }

Developing

It is recommended to create a virtualenv for development and then install all requirements for tests:

python3 -m pip install -U requirements.txt
python3 -m pip install -U ansible ansible-lint yamllint molecule-plugins[docker,lint] pytest pytest-testinfra

After doing so you can run the molecule tests with:

PY_COLORS=1 ANSIBLE_FORCE_COLOR=1 MOLECULE_DISTRO=ubuntu2004 molecule test

Or run the alternate playbook for testing when a specific version is requested:

PY_COLORS=1 ANSIBLE_FORCE_COLOR=1 MOLECULE_DISTRO=ubuntu2004 MOLECULE_PLAYBOOK=converge-version.yml molecule test

Debugging

If the service fails to start you can figure out why by looking at the output of Caddy.

systemctl status caddy -l

If something doesn't seem right, open an issue!

Contributing

Pull requests are welcome. Please test your changes beforehand with vagrant:

vagrant up
vagrant provision   # (since it already provisioned there should be no changes here)
vagrant destroy

caddy-ansible's People

Contributors

0x46616c6b avatar antoinerrr avatar b-reich avatar c35sys avatar computerlyrik avatar darrenmeehan avatar depado avatar derimagia avatar jgeusebroek avatar joelnb avatar klauern avatar lorenzbischof avatar lp-mbel avatar mikelococo avatar mikevader avatar norrland avatar notmarrco avatar paulfantom avatar perflyst avatar rdeknijf avatar ruzickap avatar soloradish avatar stevelle avatar superq avatar tevino avatar thgh avatar xiruizhao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

caddy-ansible's Issues

The systemd file is broken

In the systemd file, there are too many quotation marks and so the job fails.

ExecStart="/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile" is correct, but the job creates
ExecStart="/usr/local/bin/caddy" run --environ --config "/etc/caddy/Caddyfile"

which fails.

Set capability on the binary file failed on second run

I using this role on my rpi (rasperry pi os bullseye)

on my first run:

TASK [caddy_ansible.caddy_ansible : Set capability on the binary file to be able to bind to TCP port <1024] ***********
changed: [zigbeepi.lan]

on my second run:

TASK [caddy_ansible.caddy_ansible : Set capability on the binary file to be able to bind to TCP port <1024] ***********
fatal: [zigbeepi.lan]: FAILED! => {"changed": false, "msg": "Unable to get capabilities of /usr/local/bin/caddy", "stderr": "", "stderr_lines": [], "stdout": "/usr/local/bin/caddy cap_net_bind_service=eip", "stdout_lines": ["/usr/local/bin/caddy cap_net_bind_service=eip"]}

maybe this helps ansible/ansible#72662

Systemd version determination fails on Ubuntu 20.04

I am using the caddy-ansible role to install caddy on Ubuntu 20.04. Ubuntu 20.04 has systemd version 245.

I noticed that the generated caddy.service file has the StartLimitInterval and StartLimitBurst values in the Service section. Based on the logic in the caddy.service template, I would only expect these values in that section when caddy_systemd_version is < 230.

I ran ansible with verbose logging, and I noticed that it seems to pick up the apt package value instead of the pure version number:

TASK [caddy_ansible.caddy_ansible : Set systemd version fact] ******************
task path: /home/mike/.ansible/roles/caddy_ansible.caddy_ansible/tasks/preflight.yml:15
ok: [lab1.ipa3.mccllstr.net] => {
    "ansible_facts": {
        "caddy_systemd_version": "(245.4-4ubuntu3.6)"
    },
    "changed": false
}

I think this is because systemctl --version returns this on Ubuntu 20.04: systemd 245 (245.4-4ubuntu3.6), and the preflight.yml file is picking up "(245.4-4ubuntu3.6)" instead of "245".

You need to install "jmespath" prior to running json_query filter

error:

TASK [caddy-ansible : Set variable with list of available releases] ************
fatal: [default]: FAILED! => {"msg": "You need to install \"jmespath\" prior to running json_query filter"}

Error showed today (18.12.2023r). Previous build was performed 3 days ago (15.12.2023r) without issues

build on image hashicorp/packer:1.9.1

packer (machine.pkr.hcl):

build {
  ......

  provisioner "ansible" {
    user          = "app"
    galaxy_file   = "./ansible/requirements.yml"
    playbook_file = "./ansible/playbook-step-2.yml"
    ansible_env_vars = [
      "ANSIBLE_SSH_ARGS='-oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedKeyTypes=ssh-rsa'"
    ]
    extra_arguments = [
      "--extra-vars",
      "app=${var.app} env=${var.env}"
    ]
  }

galaxy file (requirements.yml)

roles:
- { src: "git+https://github.com/caddy-ansible/caddy-ansible.git" }

playbook file (playbook-step-2.yml)

- name: Provision Image - Step 2
  hosts: all
  become: true
  tasks:
    - name: ensure exists caddy http server
      include_role: role=caddy-ansible
      vars:
        caddy_setcap: true
        caddy_systemd_capabilities_enabled: true
        caddy_systemd_capabilities: "CAP_NET_BIND_SERVICE"
        caddy_config: "{{ lookup('template', 'templates/Caddyfile.j2') }}"

    - name: enabled caddy
      systemd: name=caddy state=started

Ensure examples are compatible with Caddy v2

There are some example playbooks in the README which have not been fully updated to be compatible with Caddy v2. We should check them & make any required changes to ensure compatibility.

Reinstate PGP verification

It would be nice to one day reinstate the PGP verification removed in #6

Currently the builds from github and from the build server are not signed so this verification is not possible.

v2 support ?

Hi there

Now that Caddy v2 is out, wanted to know, does this role support v2 ? I guess so, but might want to add a word about v1 / v2 support in the README.

Best regards,

Retain existing /etc/caddy/Caddyfile

Hi, thanks for this awesome Ansible role. I noticed in subsequent runs that it overwrites the Caddyfile at /etc/caddy/Caddyfile. Is there a flag to retain the file if it already exists?

Ansible check fails

When running an ansible playbook including caddy role in check mode (--check), it fails.

If run before the first normal run, the failing task is : Get all Caddy releases. The directory /home/caddy is missing.

TASK [caddy_ansible.caddy_ansible : Get all Caddy releases] ********************
fatal: [jira.corp-stg.caascad.com]: FAILED! => {
 "changed": false,
 "checksum_dest": null,
 "checksum_src": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
 "dest": "/home/caddy/releases.txt",
 "elapsed": 0,
 "msg": "Destination /home/caddy does not exist",
 "src": "/home/cloud/.ansible/tmp/ansible-tmp-1670335729.277793-23854-8540111055719/tmp7maxb6dg",
 "url": "https://api.github.com/repos/caddyserver/caddy/git/refs/tags"
}

When run after an apply, the failing task is : Set Caddy tag

TASK [caddy_ansible.caddy_ansible : Set Caddy tag] *****************************
fatal: [jira.corp-stg.caascad.com]: FAILED! => {
 "msg": "The task includes an option with an undefined variable. The error was: Unable to look up a name or access an attribute in template string ({{ (latest_caddy_release.content | from_json).get('tag_name') }}).
 Make sure your variable name does not contain invalid characters like '-': the JSON object must be str, bytes or bytearray, not AnsibleUndefined
 
 The error appears to be in '/run/user/1000/trackbone-3026485525/.ansible/roles/caddy_ansible.caddy_ansible/tasks/github-url.yml': line 9, column 3, but may
 be elsewhere in the file depending on the exact syntax problem.
 
 The offending line appears to be:
 
 
 - name: Set Caddy tag
   ^ here
   "
}

Affected versions tested : v3.2.0

First time installation: Unable to reload service caddy: caddy.service is not active, cannot reload.


TASK [caddy_ansible.caddy_ansible : Create Caddyfile] ******************************************************************************************************************************************************
Monday 25 April 2022  11:34:59 +0800 (0:00:00.348)       0:03:00.293 ********** 
changed: [my-testing-node]

TASK [caddy_ansible.caddy_ansible : Template systemd service] **********************************************************************************************************************************************
Monday 25 April 2022  11:34:59 +0800 (0:00:00.635)       0:03:00.928 ********** 
changed: [my-testing-node]

TASK [caddy_ansible.caddy_ansible : Set capability on the binary file to be able to bind to TCP port <1024] ************************************************************************************************
Monday 25 April 2022  11:35:00 +0800 (0:00:00.962)       0:03:01.890 ********** 
changed: [my-testing-node]

RUNNING HANDLER [caddy_ansible.caddy_ansible : Restart caddy] **********************************************************************************************************************************************
Monday 25 April 2022  11:35:01 +0800 (0:00:00.414)       0:03:02.305 ********** 
changed: [my-testing-node]

RUNNING HANDLER [caddy_ansible.caddy_ansible : Reload caddy] ***********************************************************************************************************************************************
Monday 25 April 2022  11:35:02 +0800 (0:00:01.117)       0:03:03.422 ********** 
fatal: [my-testing-node]: FAILED! => {
    "changed": false
}

MSG:

Unable to reload service caddy: caddy.service is not active, cannot reload.

[my-testing-node] HANDLER: caddy_ansible.caddy_ansible : Reload caddy (debug)

It should check if it started already before reloading? It can be fixed by running Ansible again.

Warning: "certutil" is not available

During caddy install this message pops up:

Warning: "certutil" is not available, install "certutil" with "apt install libnss3-tools" or "yum install nss-tools" and try again

Proposal: Install libnss3-tools / nss-tools as part of the role.

Release?

While creating prometheus demo site (https://github.com/prometheus/demo-site) We hit an issue when using ansible 2.9 with this role installed via ansible-galaxy.

Issue was solved 3 months ago with 325e584 but since there was no release with that commit, ansible-galaxy doesn't serve fixed version. Could there be a new release so the issue is gone?

Systemd differences between role and packages version

I am a little curious about differences between this role and caddy packaged systemd.

User/Group - that's obvious (and configurable), although I am not sure if bash should be set or /usr/sbin/nologin

After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service

vs

After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

vs

[Service]
Restart=on-failure

; User and group the process will run as.
User=www-data
Group=www-data

; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/etc/ssl/caddy

ExecStart="/usr/local/bin/caddy" run --environ --config "/etc/caddy/Caddyfile" 
ExecReload="/usr/local/bin/caddy" reload --config "/etc/caddy/Caddyfile"

; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
LimitNOFILE=1048576

; Use private /tmp and /var/tmp, which are discarded after caddy stops.
PrivateTmp=true
; Use a minimal /dev
PrivateDevices=true
; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
ProtectHome=false
; Make /usr, /boot, /etc and possibly some more folders read-only.
ProtectSystem=full
; ... except /etc/ssl/caddy, because we want Letsencrypt-certificates there.
;   This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
ReadWriteDirectories=/etc/ssl/caddy /var/log/caddy

; The following additional security directives only work with systemd v229 or later.
; They further retrict privileges that can be gained by caddy.
; Note that you may have to add capabilities required by any plugins in use.
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

What interests me is:

  • are private/protect providing additional security measures or lower them?
  • should you require CAP_NET_ADMIN?
  • Should you use Type=notify?
  • Should reload use --force flag?

I am also skeptical about:

StartLimitIntervalSec=86400
StartLimitBurst=5

If you make error 5 times in your config during one day - you will not be able to restart without systemd-reload. By default systemd use 10/5.

Fix travis tests

Currently the tests are failing on Travis in this task:

TASK [caddy-ansible : Get all Caddy releases] **********************************
fatal: [jessie]: FAILED! => {"changed": false, "dest": "/home/caddy/releases.txt", "msg": "Request failed", "response": "HTTP Error 403: Forbidden", "state": "absent", "status_code": 403, "url": "https://api.github.com/repos/mholt/caddy/git/refs/tags"}
fatal: [centos7]: FAILED! => {"changed": false, "dest": "/home/caddy/releases.txt", "msg": "Request failed", "response": "HTTP Error 403: Forbidden", "state": "absent", "status_code": 403, "url": "https://api.github.com/repos/mholt/caddy/git/refs/tags"}
changed: [stretch]
changed: [xenial]
changed: [fedora]

I think this might be because the requests are being rate limited - I was able to reproduce this myself by simply running watch -n 1 curl -sSL https://api.github.com/repos/mholt/caddy/git/refs/tags for a little bit until I started getting 403 responses with this body:

{
  "message": "API rate limit exceeded for x.x.x.x. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
  "documentation_url": "https://developer.github.com/v3/#rate-limiting"
}

I don't think having to authenticate these requests would be a great solution so I will look for an alternate one.

CI intermittent failures

I have observed intermittent CI failures on the 18.04 container. This seems to be due to the cache_valid_time thinking that no update is needed.

I have opened geerlingguy/docker-ubuntu1804-ansible#24 which seems to resolve that issue. Hopefully that will be merged & solve things but if not we may need to do something on our side as a workaround.

I have never seen this failure on the 20.04 container although logically it should also happen there. Possibly in all cases where the 20.04 would fail the 18.04 has already failed. Or possibly 20.04 has another mechanism in place to prevent this.

Configurable caddy.service name

Would it be possible to add the caddy service name as a variable, e.g. caddy_service_name: caddy.service? My use case is wanting to run multiple caddy servers on a single host and have them not conflict with one another. This is the only conflict I have.

Using this role fails because caddy repo changed

When using the role, the provision fails. This is likely because caddy changed its repository:

TASK [caddy_ansible.caddy_ansible : Get all Caddy releases] ********************
fatal: [default]: FAILED! => {"changed": false, "dest": "/home/caddy/releases.txt", "elapsed": 0, "msg": "Request failed", "response": "HTTP Error 404: Not Found", "status_code": 404, "url": "https://api.github.com/repos/mholt/caddy/git/refs/tags"}

The underlying Github repo (mholt/caddy) does not exist anymore, since it was moved to https://github.com/caddyserver/caddy .

Therefore, the rest endpoint in tasks/main.yml must change to: https://api.github.com/repos/caddyserver/caddy/git/refs/tags

Is procps still needed?

According to a comment, packages-apt.yml loads procps because the kill binary is needed in the service file, which I take to mean the caddy.service systemd service file. I don't see where in that file the kill binary is used, however. IIUC, systemd can send its own SIGTERM etc. and wouldn't necessarily need kill.

So is procps still needed?

Affected lines:

# This is required because it provides the /bin/kill binary used in the service file
- name: Install procps
  ansible.builtin.apt:
    name: procps
    state: present

https://github.com/caddy-ansible/caddy-ansible/blob/master/tasks/packages-apt.yml#L8-L14

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.