Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faasd #345

Draft
wants to merge 40 commits into
base: master
Choose a base branch
from
Draft

Faasd #345

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3e9e0ba
initial faasd
EnigmaCurry Oct 18, 2024
2b1d78c
readme
EnigmaCurry Oct 18, 2024
a1fef26
makefile
EnigmaCurry Oct 19, 2024
70a4d80
Merge branch 'master' into faasd
EnigmaCurry Oct 19, 2024
d2d94e4
sysbox
EnigmaCurry Oct 19, 2024
e10115f
docker-compose
EnigmaCurry Oct 19, 2024
729e89b
privileged
EnigmaCurry Oct 19, 2024
9ea9fbd
README
EnigmaCurry Oct 19, 2024
f15c3b4
README
EnigmaCurry Oct 19, 2024
fca95b4
README
EnigmaCurry Oct 19, 2024
1811f48
README
EnigmaCurry Oct 19, 2024
4181abd
README
EnigmaCurry Oct 19, 2024
daee7f3
README
EnigmaCurry Oct 19, 2024
a5bc7ad
README
EnigmaCurry Oct 19, 2024
0caefcc
faasd
EnigmaCurry Oct 19, 2024
3861b9b
ports
EnigmaCurry Oct 19, 2024
8868b56
entrypoint
EnigmaCurry Oct 19, 2024
4dbe151
entrypoint
EnigmaCurry Oct 19, 2024
27fa9f0
entrypoint
EnigmaCurry Oct 19, 2024
ea7c8f1
entrypoint
EnigmaCurry Oct 19, 2024
53d90bb
dockerfile
EnigmaCurry Oct 19, 2024
f7bf552
overlayfs
EnigmaCurry Oct 19, 2024
7feec7f
dockerfile
EnigmaCurry Oct 19, 2024
0c7cd0e
fuse-overlayfs
EnigmaCurry Oct 19, 2024
62b17d4
faasd
EnigmaCurry Oct 19, 2024
49a659c
faasd
EnigmaCurry Oct 19, 2024
01d97c1
README
EnigmaCurry Oct 19, 2024
9c92d31
README
EnigmaCurry Oct 19, 2024
68cbee4
README
EnigmaCurry Oct 19, 2024
d653f64
readme
EnigmaCurry Oct 19, 2024
0706a04
README
EnigmaCurry Oct 19, 2024
8942774
README
EnigmaCurry Oct 19, 2024
b877c86
README
EnigmaCurry Oct 19, 2024
158851d
faasd
EnigmaCurry Oct 19, 2024
d523626
faasd
EnigmaCurry Oct 19, 2024
83f0739
auth
EnigmaCurry Oct 19, 2024
e1032a8
volumes
EnigmaCurry Oct 19, 2024
c9612c4
mount
EnigmaCurry Oct 19, 2024
f4011b0
README
EnigmaCurry Oct 19, 2024
45c4363
README
EnigmaCurry Oct 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ Install these other services at your leisure/preference:
* [DOH-server](doh-server#readme) - a DNS-over-HTTPs proxy resolver
* [DrawIO](drawio#readme) - a diagram / whiteboard editor tool
* [Ejabberd](ejabberd#readme) - an XMPP (Jabber) server
* [Faasd](faasd#readme) - a lightweight "serverless" compute platform
* [Filestash](filestash#readme) - a web based file manager with customizable backend storage providers
* [FreshRSS](freshrss#readme) - an RSS reader / proxy
* [Glances](glances#readme) - a cross-platform system monitoring tool
Expand Down
40 changes: 40 additions & 0 deletions faasd/.env-dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
FAASD_TRAEFIK_HOST=faasd.example.com

# The name of this instance. If there is only one instance, use 'default'.
FAASD_INSTANCE=

## You can run the container in privileged (root) mode if necessary?:
FAASD_PRIVILEGED=false

# Filter access by IP address source range (CIDR):
##Disallow all access: 0.0.0.0/32
##Allow all access: 0.0.0.0/0
FAASD_IP_SOURCERANGE=0.0.0.0/0

# HTTP Basic Authentication:
# Use `make config` to fill this in properly, or set this to blank to disable.
FAASD_HTTP_AUTH=

# OAUTH2
# Set to `true` to use OpenID/OAuth2 authentication via the
# traefik-forward-auth service in d.rymcg.tech.
# Using OpenID/OAuth2 will require login to access your app,
# but it will not affect what a successfully logged-in person can do in your
# app. If your app has built-in authentication and can check the user
# header that traefik-forward-auth sends, then your app can limit what the
# logged-in person can do in the app. But if your app can't check the user
# header, or if your app doesn't have built-in authentication at all, then
# any person with an account on your Gitea server can log into your app and
# have full access.
FAASD_OAUTH2=
# In addition to Oauth2 authentication, you can configure basic authorization
# by entering which authorization group can log into your app. You create
# groups of email addresses in the `traefik` folder by running `make groups`.
FAASD_OAUTH2_AUTHORIZED_GROUP=

# Mutual TLS (mTLS):
# Set true or false. If true, all clients must present a certificate signed by Step-CA:
FAASD_MTLS_AUTH=false
# Enter a comma separated list of client domains allowed to connect via mTLS.
# Wildcards are allowed and encouraged on a per-app basis:
FAASD_MTLS_AUTHORIZED_CERTS=*.clients.faasd.example.com
28 changes: 28 additions & 0 deletions faasd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
ROOT_DIR = ..
include ${ROOT_DIR}/_scripts/Makefile.projects
include ${ROOT_DIR}/_scripts/Makefile.instance

.PHONY: config-hook
config-hook:
@${BIN}/reconfigure_ask ${ENV_FILE} FAASD_TRAEFIK_HOST "Enter the faasd domain name" faasd${INSTANCE_URL_SUFFIX}.${ROOT_DOMAIN}
@${BIN}/reconfigure ${ENV_FILE} FAASD_INSTANCE=$${instance:-default}
@${BIN}/reconfigure_auth ${ENV_FILE} FAASD
@echo ""

.PHONY: override-hook
override-hook:
#### This sets the override template variables for docker-compose.instance.yaml:
#### The template dynamically renders to docker-compose.override_{DOCKER_CONTEXT}_{INSTANCE}.yaml
#### These settings are used to automatically generate the service container labels, and traefik config, inside the template.
#### The variable arguments have three forms: `=` `=:` `=@`
#### name=VARIABLE_NAME # sets the template 'name' field to the value of VARIABLE_NAME found in the .env file
#### # (this hardcodes the value into docker-compose.override.yaml)
#### name=:VARIABLE_NAME # sets the template 'name' field to the literal string 'VARIABLE_NAME'
#### # (this hardcodes the string into docker-compose.override.yaml)
#### name=@VARIABLE_NAME # sets the template 'name' field to the literal string '${VARIABLE_NAME}'
#### # (used for regular docker-compose expansion of env vars by name.)
@${BIN}/docker_compose_override ${ENV_FILE} project=:faasd instance=@FAASD_INSTANCE traefik_host=@FAASD_TRAEFIK_HOST http_auth=FAASD_HTTP_AUTH http_auth_var=@FAASD_HTTP_AUTH ip_sourcerange=@FAASD_IP_SOURCERANGE oauth2=FAASD_OAUTH2 authorized_group=FAASD_OAUTH2_AUTHORIZED_GROUP enable_mtls_auth=FAASD_MTLS_AUTH mtls_authorized_certs=FAASD_MTLS_AUTHORIZED_CERTS privileged=FAASD_PRIVILEGED

.PHONY: shell
shell:
@make --no-print-directory docker-compose-shell SERVICE=faasd
199 changes: 199 additions & 0 deletions faasd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Faasd

[Faasd](https://github.com/openfaas/faasd) is a lightweight compute
platform for running "serverless" functions in short-lived containers
that are created on demand. Faasd does not natively support Docker (it
runs its own container runner and it is dependent on systemd),
however, it can be forced to run in Docker with
[sysbox](https://github.com/nestybox/sysbox#readme).

## Configure sysbox on the Docker host

Login to your Docker host as root, and install sysbox:

```
## Run this on the docker host:
(set -ex
sudo DEBIAN_FRONTEND=noninteractive apt install -y \
jq fuse rsync linux-headers-$(uname -r)
TMP_FILE=$(mktemp)
wget -O ${TMP_FILE} "https://downloads.nestybox.com/sysbox/releases/v0.6.4/sysbox-ce_0.6.4-0.linux_$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/').deb"
dpkg -i ${TMP_FILE}
rm -f ${TMP_FILE})
```

## Config faasd

```
## Run this on your workstation:
d make faasd config
```

Enter the domain name to use for the service:

```stdout
# FAASD_TRAEFIK_HOST: Enter the faasd domain name (eg. faasd.example.com)
# : faasd.example.com
```

For testing purposes, you should choose to enable HTTP Basic
Authentication, with a username and password:

```
? Do you want to enable sentry authorization in front of this app (effectively making the entire site private)?
No
> Yes, with HTTP Basic Authentication
Yes, with Oauth2
Yes, with Mutual TLS (mTLS)

Enter the username for HTTP Basic Authentication
: test

Enter the passphrase for test (leave blank to generate a random passphrase)
: a_secure_passphrase

> Would you like to create additional usernames (for the same access privilege)? No

> Would you like to export the usernames and cleartext passwords to the file passwords.js
n? No
```


## Install faasd

```
## Run this on your workstation:
d make faasd install
```

## Finish faasd install via the shell

Enter the faasd container shell:

```
## Run this on your workstation:
d make faasd shell
```

Inside the shell, run the faasd installation script:

```
# Run this in the faasd container shell:
~/git/vendor/openfaas/faasd/hack/install.sh
```

## Setup container registry

Faasd deploys its containers by pulling from a Docker container
registry, so you must provision one yourself or use a third party
service.

* Create a local Docker registry for testing purposes:

```
## Inside the faasd container shell:
podman run -d -p 5000:5000 --name registry registry:2
```

* Create service files to start the registry on container startup:

```
## Inside the faasd container shell:
podman generate systemd --name registry --files --restart-policy always
mv container-registry.service /etc/systemd/system/
systemctl enable --now container-registry.service
```

## Retrieve Faasd admin password

Retrieve the password and save it someplace safe (the PASSWORD var
will be used temporarily):

```
## Inside the faasd container shell:
PASSWORD=$(sudo cat /var/lib/faasd/secrets/basic-auth-password)
echo ${PASSWORD}
```

### Log in with faas-cli

```
## Inside the faasd container shell:
export OPENFAAS_URL=http://localhost:8080
echo $PASSWORD | faas-cli login --password-stdin
```

## Create and test your own function

Create a new project directory (`hello`):

```
## Inside the faasd container shell:
faas-cli new --lang python3 \
hello-world \
--prefix localhost:5000
```

Build and install the image:

```
## Inside the faasd container shell:
faas-cli up -f hello-world.yml
```

Test the newly deployed function:

```
## Inside the faasd container shell:
echo "Hello faasd" | faas-cli invoke hello-world
# Hello faasd
```

Test via HTTP:

```
## Inside the faasd container shell:
curl -d "Hello curl" http://127.0.0.1:8080/function/hello-world
# Hello curl
```

Test asynchronous function with a callback webhook. Create a [postb.in
endpoint](https://www.postb.in) to use as a temporary webhook
receiver:

```
## Inside the faasd container shell:
POSTBIN=$(curl -X POST -d "" https://www.postb.in/api/bin | jq -r ".binId")
```

Test the function and pass the webhook:

```
## Inside the faasd container shell:
curl -d "Bonjour postb.in" \
http://127.0.0.1:8080/async-function/hello-world \
--header "X-Callback-Url: https://www.postb.in/${POSTBIN}"
```

Retrieve (and remove) the response from the receiver:

```
## Inside the faasd container shell:
curl https://www.postb.in/api/bin/${POSTBIN}/req/shift | jq -r ".body | keys[]"
```

This should respond with the same text you sent: `Bonjour postb.in`.

## Test public route to function

```
curl -L -d "Hello public" https://test:[email protected]/function/hello-world
```

This should route your domain name (`faasd.example.com`) TLS port
`443` through Traefik, verifying your username and password, and then
forward to the faasd backend port `8080`.

## Test faas-cli from remote workstation

Gonna need a registry for this...
67 changes: 67 additions & 0 deletions faasd/docker-compose.instance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#! This is a ytt template file for docker-compose.override.yaml
#! References:
#! https://carvel.dev/ytt
#! https://docs.docker.com/compose/extends/#adding-and-overriding-configuration
#! https://github.com/enigmacurry/d.rymcg.tech#overriding-docker-composeyaml-per-instance

#! ### Standard project vars:
#@ load("@ytt:data", "data")
#@ project = data.values.project
#@ instance = data.values.instance
#@ context = data.values.context
#@ traefik_host = data.values.traefik_host
#@ ip_sourcerange = data.values.ip_sourcerange
#@ enable_http_auth = len(data.values.http_auth.strip()) > 0
#@ http_auth = data.values.http_auth_var
#@ privileged = data.values.privileged == "true"
#@ enabled_middlewares = []

#@yaml/text-templated-strings
services:
faasd:
#@ service = "faasd"
labels:
- "backup-volume.stop-during-backup=true"
#! Services must opt-in to be proxied by Traefik:
- "traefik.enable=true"

#! 'router' is the fully qualified key in traefik for this router/service: project + instance + service
#@ router = "{}-{}-{}".format(project,instance,service)

#! The host matching router rule:
- "traefik.http.routers.(@= router @).rule=Host(`(@= traefik_host @)`)"
- "traefik.http.routers.(@= router @).entrypoints=websecure"
#@ enabled_middlewares.append("{}-ipallowlist".format(router))
- "traefik.http.middlewares.(@= router @)-ipallowlist.ipallowlist.sourcerange=(@= ip_sourcerange @)"

#@ if enable_http_auth:
#@ enabled_middlewares.append("{}-basicauth".format(router))
- "traefik.http.middlewares.(@= router @)-basicauth.basicauth.users=(@= http_auth @)"
- "traefik.http.middlewares.(@= router @)-basicauth.basicauth.headerField=X-Forwarded-User"
#@ end

- "traefik.http.services.(@= router @).loadbalancer.server.port=8080"

#! Apply all middlewares (do this at the end!)
- "traefik.http.routers.(@= router @).middlewares=(@= ','.join(enabled_middlewares) @)"

#@ if privileged:
privileged: true
#@ else:
sysctls:
- net.ipv4.ip_unprivileged_port_start=1024
security_opt:
- no-new-privileges:true
#@ end

volumes:
- etc:/etc
- home:/home
- usr_local:/usr/local
- var_lib:/var/lib
- opt:/opt
- lib_systemd:/lib/systemd
#@ if privileged:
- /run:/run
- /sys/fs/cgroup:/sys/fs/cgroup:ro
#@ end
17 changes: 17 additions & 0 deletions faasd/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

volumes:
etc:
home:
usr_local:
var_lib:
opt:
lib_systemd:

services:
faasd:
## sysbox-runc allows to run systemd inside the container:
runtime: sysbox-runc
hostname: faasd-${FAASD_INSTANCE:-default}-1
build:
context: faasd
restart: unless-stopped
Loading