From 5ef6881bb4a6db5d2d53205be1a7737ecdf0fcff Mon Sep 17 00:00:00 2001 From: Tomi Mickelsson Date: Sun, 17 Mar 2024 09:40:27 +0200 Subject: [PATCH] ansible installs caddy --- README.md | 66 ++++++--------------------------------- ansible/install-caddy.yml | 26 +++++++++++++++ ansible/myhosts.ini | 3 ++ conf/caddy.conf | 32 +++++++++++++++++++ conf/uwsgi.ini | 5 +-- www/index.html | 5 +++ 6 files changed, 79 insertions(+), 58 deletions(-) create mode 100644 ansible/install-caddy.yml create mode 100644 conf/caddy.conf create mode 100644 www/index.html diff --git a/README.md b/README.md index 0f96299..79d8209 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ Update March 2024: Ansible scripts for automatic install to cloud. * [Logging](#logging) * [Tests](#tests) * [Deploy to cloud](#deploy-to-cloud) -* [Nginx](#nginx) * [Security](#security) * [Scaling up](#scaling-up) * [Run in Raspberry](#run-in-raspberry) @@ -151,6 +150,7 @@ The whole of this server fits into a small set of files: ``` ├── /ansible/ # ansible files for automated cloud install ├── /conf/ # configuration files +│ ├── /caddy.conf # config for Caddy www proxy that ansible setups │ ├── /favicon.ico # site icon │ ├── /loginscript.sh # docker shell login script, sets paths │ ├── /pydaemon.service # systemd daemon config @@ -188,6 +188,7 @@ The whole of this server fits into a small set of files: │ ├── /test_api.py # test API methods │ ├── /test_redis.py # test redis module │ └── /sample.log.txt # sample logging output from api test +├── /www/ # static files for Caddy ├── build.sh # build Docker image in dev mode ├── Dockerfile # docker image config ├── requirements.txt # python 3rd party dependencies @@ -639,10 +640,12 @@ There are endless ways to deploy server software to cloud, X amount of tools and [Ansible](https://www.ansible.com/) is one of the best lightweigt tools to automate infra tasks. It simply runs commands over the SSH against all your servers. -I have prepared 4 Ansible scripts to setup RESTPie3 quickly on a Linux server(s). These steps have been verified to work with Debian 12.5 "bookworm". +I have prepared Ansible scripts to setup RESTPie3 quickly on a Linux server(s). These steps have been verified to work with Debian 12.5 "bookworm". + +The scripts setup Redis + PostgreSQL + RESTPie3 + Caddy on your server(s). [Caddy](https://caddyserver.com) is a solid and simple www server written in Go that can run as a proxy in front of uwsgi. Prerequisites: -- Have a root ssh access to your server(s) via ssh publickey, and use ssh-agent to store your private key so you don't have to type it all the time. After setup you should disable server root access. +- Have a root ssh access to your server(s) via ssh publickey, and use ssh-agent to store your private key so you don't have to type the passphare all the time. After setup you should disable server root access. - Update your server to the latest versions: `apt update & apt upgrade` - Locally create a new ssh-key for the user-level Linux account that is later used for deploys `ssh-keygen -t rsa -f ~/.ssh/id_myapp -C 'restpie3 deploy account'` @@ -651,14 +654,15 @@ Prerequisites: - Put your desired config/secrets into [vars.yml](ansible/vars.yml) Note: do NOT commit secrets into git! Move this file elsewhere or put into `.gitignore` - Write the IP-address or domain name of your server into [myhosts.ini](ansible/myhosts.ini). If you have multiple servers, write them all here. -Then run these 3 scripts to setup Redis + PostgreSQL + RESTPie3 on your server(s): +Then run these scripts: cd restpie3/ansible/ ansible-playbook -i myhosts.ini install-redis.yaml + ansible-playbook -i myhosts.ini install-caddy.yaml ansible-playbook -i myhosts.ini install-db.yaml ansible-playbook -i myhosts.ini install-app.yaml -Now you should have a running RESTPie3 at the server you configured. Point your browser there. +Now you should have a running RESTPie3 at the server you configured. Point your browser there. You should see text `RESTPie3 setup works!` Your code updates from local machine to server can be deployed with: @@ -666,55 +670,7 @@ Your code updates from local machine to server can be deployed with: Later you might want to run this script from Github Action to have consistent automation. -Finally do enhance the security of this simple setup: -- Have a load balancer as a service and then run your servers in a private network. Atleast install a proxy server in front of RESTPie3, like [Nginx](https://www.nginx.com/) or [Caddy](https://caddyserver.com/). Only allow HTTPS traffic. -- Run uwsgi as a low-privilege user behind the proxy, see [uwsgi.ini](conf/uwsgi.ini) -- Disable ssh root login after initial setup. - - -Nginx ------ - -Few words about Nginx: if you want to run this API server and your front-end -under the same domain, and you are using Nginx, you can have the following -Nginx config to send all /api/ requests to Python server and other requests to -other destinations, like to Node and file system: - - - # in nginx config: - - # to python api server - location /api/ { - uwsgi_pass localhost:8010; - include uwsgi_params; - uwsgi_param X-Real-IP $remote_addr; - uwsgi_param X-Real-Host $host; - } - - # static files - location /static/ { - root /path/to/myfiles; - # note that you must have /path/to/myfiles/static/ folder, - # unless rewriting the url - try_files $uri /index.html =404; - } - - # to Node server - location / { - proxy_pass http://localhost:8080; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - } - - -And then enable the uwsgi-listener in [uwsgi.ini](conf/uwsgi.ini): - - # in uwsgi.ini: - [uwsgi-production] - uwsgi-socket = localhost:8010 +For a production setup you should harden the security of this simple setup with the usual steps like: create a private network behind a load balancer, disable ssh root login, carefully build access control, etc. Security @@ -738,8 +694,6 @@ A few words about security practices in this software: * authorization is enforced via user roles and function decorator, not requiring complex code * uwsgi supports running code as a lower privileged user -* uwsgi supports SSL certificates (but a load balancer or nginx in front is - recommended as SSL endpoint) Of course the overall security of the service is also heavily dependent on the configuration of the server infrastructure and access policies. diff --git a/ansible/install-caddy.yml b/ansible/install-caddy.yml new file mode 100644 index 0000000..4f8e956 --- /dev/null +++ b/ansible/install-caddy.yml @@ -0,0 +1,26 @@ + +- name: Install Caddy www server + hosts: wwwhost + # assumes you have static files at /app/www/ + + vars_files: + - vars.yml + + tasks: + - name: Install Caddy + ansible.builtin.apt: + pkg: + - caddy + + - name: Copy our caddy config + ansible.builtin.copy: + src: "{{ src_folder }}/conf/caddy.conf" + dest: /etc/caddy/Caddyfile + owner: root + group: root + mode: u=rw,g=r,o=r + + - name: Restart caddy + ansible.builtin.systemd_service: + state: restarted + name: caddy diff --git a/ansible/myhosts.ini b/ansible/myhosts.ini index 5a20bad..7df957e 100644 --- a/ansible/myhosts.ini +++ b/ansible/myhosts.ini @@ -9,3 +9,6 @@ [dbhost] 10.10.10.10 ansible_ssh_user=root + +[wwwhost] +10.10.10.10 ansible_ssh_user=root diff --git a/conf/caddy.conf b/conf/caddy.conf new file mode 100644 index 0000000..5d90dee --- /dev/null +++ b/conf/caddy.conf @@ -0,0 +1,32 @@ +# The Caddyfile is an easy way to configure your Caddy web server. +# +# Unless the file starts with a global options block, the first +# uncommented line is always the address of your site. +# +# To use your own domain name (with automatic HTTPS), first make +# sure your domain's A/AAAA DNS records are properly pointed to +# this machine's public IP, then replace ":80" below with your +# domain name. + +:80 { + # Set this path to your site's directory. + root * /app/www/ + + # Enable the static file server. + file_server + + # Another common task is to set up a reverse proxy: + # reverse_proxy localhost:8080 + + # Or serve a PHP site through php-fpm: + # php_fastcgi localhost:9000 + + # forward to restpie3 + handle_path /api/* { + rewrite * /api{uri} + reverse_proxy localhost:8110 + } +} + +# Refer to the Caddy docs for more information: +# https://caddyserver.com/docs/caddyfile diff --git a/conf/uwsgi.ini b/conf/uwsgi.ini index 29c650c..d5beba5 100644 --- a/conf/uwsgi.ini +++ b/conf/uwsgi.ini @@ -62,7 +62,8 @@ mule = py/mule1.py [uwsgi-production] plugins = corerouter,python3,logfile,spooler,http env=PYSRV_CONFIG_PATH=/app/real-server-config.json -http = :80 +# http :8110 is externally available, localhost:8110 is not +http = localhost:8110 # if using nginx and uwsgi_pass: # uwsgi-socket = localhost:8010 master = 1 @@ -87,7 +88,7 @@ vacuum = true logger = file:/app/app.log logger = stdio # run as this user - MUST SET LOWER PRIVILEGES! (Port 80 requires root) -; uid=appuser +uid=myapp ; gid=appgroup # workers live max this many requests and secs max-requests=100 diff --git a/www/index.html b/www/index.html new file mode 100644 index 0000000..5e8ca1a --- /dev/null +++ b/www/index.html @@ -0,0 +1,5 @@ +

RESTPie3 setup works!

+ +

This static index.html is served by Caddy from folder /app/www/

+ +

Caddy works as a proxy for RESTPie3 running here.