Skip to content

Commit

Permalink
ansible installs caddy
Browse files Browse the repository at this point in the history
  • Loading branch information
tomimick committed Mar 17, 2024
1 parent a5a42eb commit 5ef6881
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 58 deletions.
66 changes: 10 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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'`
Expand All @@ -651,70 +654,23 @@ 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:

ansible-playbook -i myhosts.ini deploy.yaml

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
Expand All @@ -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.
Expand Down
26 changes: 26 additions & 0 deletions ansible/install-caddy.yml
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions ansible/myhosts.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@

[dbhost]
10.10.10.10 ansible_ssh_user=root

[wwwhost]
10.10.10.10 ansible_ssh_user=root
32 changes: 32 additions & 0 deletions conf/caddy.conf
Original file line number Diff line number Diff line change
@@ -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
5 changes: 3 additions & 2 deletions conf/uwsgi.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions www/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<h1>RESTPie3 setup works!</h1>

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

<p>Caddy works as a proxy for RESTPie3 running <a href="/api/list">here</a>.</p>

0 comments on commit 5ef6881

Please sign in to comment.