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

Release 1.0 beta2 #55

Merged
merged 11 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions Dockerfiles/Dockerfile.alpine
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ LABEL \
###
### Build arguments
###
ARG VHOST_GEN_GIT_REF=1.0.8
ARG VHOST_GEN_GIT_REF=1.0.9
ARG WATCHERD_GIT_REF=v1.0.7
ARG CERT_GEN_GIT_REF=0.10

Expand All @@ -39,7 +39,7 @@ RUN set -eux \
${RUN_DEPS} \
\
# Install vhost-gen
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/refs/tags/${VHOST_GEN_GIT_REF}.tar.gz" \
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/${VHOST_GEN_GIT_REF}.tar.gz" \
&& tar xvfz vhost-gen.tar.gz \
&& cd "vhost-gen-${VHOST_GEN_GIT_REF}" \
&& make install \
Expand Down Expand Up @@ -120,7 +120,7 @@ RUN set -eux \
ENV MY_USER=www-data
ENV MY_GROUP=www-data
ENV HTTPD_START="httpd-foreground"
ENV HTTPD_RELOAD="/usr/local/apache2/bin/httpd -k stop"
ENV HTTPD_RELOAD="/usr/local/apache2/bin/httpd -k restart"
ENV HTTPD_VERSION="httpd -V 2>&1 | head -1 | awk '{print \$3}'"
ENV VHOSTGEN_HTTPD_SERVER="apache24"

Expand Down
6 changes: 3 additions & 3 deletions Dockerfiles/Dockerfile.debian
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ LABEL \
###
### Build arguments
###
ARG VHOST_GEN_GIT_REF=1.0.8
ARG VHOST_GEN_GIT_REF=1.0.9
ARG WATCHERD_GIT_REF=v1.0.7
ARG CERT_GEN_GIT_REF=0.10

Expand All @@ -36,7 +36,7 @@ RUN set -eux \
${RUN_DEPS} \
\
# Install vhost-gen
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/refs/tags/${VHOST_GEN_GIT_REF}.tar.gz" \
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/${VHOST_GEN_GIT_REF}.tar.gz" \
&& tar xvfz vhost-gen.tar.gz \
&& cd "vhost-gen-${VHOST_GEN_GIT_REF}" \
&& make install \
Expand Down Expand Up @@ -118,7 +118,7 @@ RUN set -eux \
ENV MY_USER=www-data
ENV MY_GROUP=www-data
ENV HTTPD_START="httpd-foreground"
ENV HTTPD_RELOAD="/usr/local/apache2/bin/httpd -k stop"
ENV HTTPD_RELOAD="/usr/local/apache2/bin/httpd -k restart"
ENV HTTPD_VERSION="httpd -V 2>&1 | head -1 | awk '{print \$3}'"
ENV VHOSTGEN_HTTPD_SERVER="apache24"

Expand Down
41 changes: 35 additions & 6 deletions Dockerfiles/data/docker-entrypoint.d/.httpd/func-backend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ set -o pipefail
### conf:phpfpm:tcp:<host>:<port> # Remote PHP-FPM server at <host>:<port>
### conf:rproxy:http:<host>:<port> # Reverse Proxy server at http://<host>:<port>
### conf:rproxy:https:<host>:<port> # Reverse Proxy server at https://<host>:<port>
### conf:rproxy:ws:<host>:<port> # Reverse Proxy (websocket) at ws://<host>:<port>
### conf:rproxy:wss:<host>:<port> # Reverse Proxy (websocket) at wss://<host>:<port>
###
###
### Format-2: file:<file>
Expand All @@ -40,6 +42,8 @@ set -o pipefail
### Examples:
### conf:rproxy:http:10.0.0.1:3000
### conf:rproxy:https:mydomain.com:8080
### conf:rproxy:ws:10.0.0.1:3000
### conf:rproxy:wss:10.0.0.1:3000
###
### Note: If no file is found, a warning will be logged and no Reverse proxy will be created.
###
Expand Down Expand Up @@ -90,7 +94,13 @@ backend_conf_is_valid() {
fi
# 3. Protocol: 'tcp', 'http' or 'https'
if ! backend_is_valid_conf_prot "${1}"; then
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http' or 'https'"
# Apache 2.2 does not have websocket support
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ]; then
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http' or 'https'."
# All other webserver have websocket support
else
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http', 'https', 'ws' or 'wss'."
fi
return 1
fi
# 4. Host
Expand All @@ -116,9 +126,22 @@ backend_conf_is_valid() {
fi
# 7. Validate conf <protocol> rproxy == http(s)?
if [ "${backend_conf_type}" = "rproxy" ]; then
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http' or 'https'"
return 1
# Apache 2.2 does not have websocket support
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ]; then
if [ "${backend_conf_prot}" != "http" ] \
&& [ "${backend_conf_prot}" != "https" ]; then
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http' and 'https'"
return 1
fi
# All other webserver have websocket support
else
if [ "${backend_conf_prot}" != "http" ] \
&& [ "${backend_conf_prot}" != "https" ] \
&& [ "${backend_conf_prot}" != "ws" ] \
&& [ "${backend_conf_prot}" != "wss" ]; then
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http', 'https', 'ws' and 'wss'"
return 1
fi
fi
fi
}
Expand Down Expand Up @@ -181,8 +204,14 @@ backend_is_valid_conf_prot() {
local value
value="$( get_backend_conf_prot "${1}" )"

if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ]; then
return 1
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ]; then
return 1
fi
else
if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ] && [ "${value}" != "ws" ] && [ "${value}" != "wss" ]; then
return 1
fi
fi
return 0
}
Expand Down
37 changes: 27 additions & 10 deletions Dockerfiles/data/docker-entrypoint.d/02-env-vars-validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,12 @@ _validate_vhost_backend() {
# 5. Validate conf <protocol>
if ! backend_is_valid_conf_prot "${value}"; then
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http' or 'https'"
# Apache 2.2 does not have websocket support
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http' or 'https'"
else
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http', 'https', 'ws' or 'wss'"
fi
_log_backend_examples "conf"
exit 1
fi
Expand All @@ -662,11 +667,21 @@ _validate_vhost_backend() {
fi
# 7. Validate conf <protocol> rproxy == http(s)?
if [ "${backend_conf_type}" = "rproxy" ]; then
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http' or 'https'"
_log_backend_examples "conf"
exit 1
# Apache 2.2 does not have websocket support
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http' and 'https'"
_log_backend_examples "conf"
exit 1
fi
else
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ] && [ "${backend_conf_prot}" != "ws" ] && [ "${backend_conf_prot}" != "wss" ]; then
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http', 'https', 'ws' and 'wss'"
_log_backend_examples "conf"
exit 1
fi
fi
fi
# 8. Validate conf <host>
Expand Down Expand Up @@ -1062,11 +1077,13 @@ _log_backend_examples() {
log "err" "Example: conf:phpfpm:tcp:10.0.0.100:9000"
log "err" "Example: conf:phpfpm:tcp:domain.com:9000"
log "err" ""
log "err" "Example: conf:rproxy:http:10.0.0.100:3000"
log "err" "Example: conf:rproxy:http:domain.com:443"
log "err" ""
log "err" "Example: conf:rproxy:https:10.0.0.100:8080"
log "err" "Example: conf:rproxy:http:10.0.0.100:8080"
log "err" "Example: conf:rproxy:https:domain.com:8443"
if [ "${VHOSTGEN_HTTPD_SERVER}" != "apache22" ]; then
log "err" ""
log "err" "Example: conf:rproxy:ws:10.0.0.100:8080"
log "err" "Example: conf:rproxy:wss:domain.com:8443"
fi
fi
if [ "${show}" = "all" ] || [ "${show}" = "file" ]; then
log "err" ""
Expand Down
2 changes: 1 addition & 1 deletion Dockerfiles/data/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ http {

# [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
# https://stackoverflow.com/questions/26357487/
server_names_hash_bucket_size 64;
server_names_hash_bucket_size 128;


# -------------------------------------------------------------------------------
Expand Down
27 changes: 23 additions & 4 deletions Dockerfiles/data/vhost-gen/templates-main/nginx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,31 @@ vhost_type:
root "__DOCUMENT_ROOT__";
index __INDEX__;

# Reverse Proxy (-r)
# Reverse Proxy (-r http(s)://ADDR:PORT)
rproxy: |
# Define the vhost to reverse proxy
# Define Reverse Proxy
location __LOCATION__ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# https://stackoverflow.com/a/72586833
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Proxy connection
proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
}

# Reverse Proxy with websocket support (-r ws(s)://ADDR:PORT)
rproxy_ws: |
# Define Reverse Proxy with Websock support
location __LOCATION__ {
# https://stackoverflow.com/a/72586833
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Websocket settings
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# Proxy connection
proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
}

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

This image is based on the official **[Apache 2.4](https://hub.docker.com/_/httpd)** Docker image and extends it with the ability to have **virtual hosts created automatically**, as well as **adding SSL certificates** when creating new directories. For that to work, it integrates two tools that will take care about the whole process: **[watcherd](https://github.com/devilbox/watcherd)** and **[vhost-gen](https://github.com/devilbox/vhost-gen)**.

From a users perspective, you mount your local project directory into the container under `/shared/httpd`. Any directory then created in your local project directory wil spawn a new virtual host by the same name. Each virtual host optionally supports a generic or custom backend configuration (**static files**, **PHP-FPM** or **reverse proxy**).
From a users perspective, you mount your local project directory into the container under `/shared/httpd`. Any directory then created in your local project directory wil spawn a new virtual host by the same name. Each virtual host optionally supports a generic or custom backend configuration: **static files**, **PHP-FPM**, **reverse proxy** (with or without **websocket** support)..

**HTTP/2 is enabled by default for all SSL connections.**

Expand Down Expand Up @@ -100,7 +100,7 @@ Below is a brief overview about most outstanding features, but I would still adv
* PHP is not included in the provided images, but you can enable a remote backend and link it to a PHP-FPM image. This allows you to easily switch PHP versions and choose one which is currently required.

#### Automated Reverse Proxy setup
* In reverse proxy mode, you can choose any http or https backend of your likings. This way you can proxy NodeJS, Python, etc. and use the webserver to add SSL in front.
* In reverse proxy mode, you can choose any http or https backend of your likings. This way you can proxy NodeJS, Python, etc. and use the webserver to add SSL in front. It distinguishes between HTTP backends (`http://`, `https://`) and Websocket backends (`ws://`, `wss://`) automatically and configures accordingly.

#### Automated SSL certificate generation
* SSL certificates are generated automatically for each virtual host if you choose to enable it
Expand Down Expand Up @@ -245,6 +245,7 @@ The given examples distinguish between two different kinds of setup: The default
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-serve-php-files-with-php-fpm-and-sync-local-permissions" >Sync local filestem permission</a><br/>
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-serve-php-files-with-php-fpm-over-https" >Serve PHP files over HTTPS</a><br/>
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-act-as-a-reverse-proxy-for-nodejs" >Reverse Proxy NodeJS</a><br/>
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-act-as-a-reverse-proxy-websockets" >Reverse Proxy Websocket</a><br/>
</td>
<td>
<strong>Unlimited vhosts</strong><br/>
Expand Down
6 changes: 4 additions & 2 deletions doc/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ The given value determines the backend (potentia remote/reveres hosts) for the m
* **Var type:** `string`
* **Requires:** `MAIN_VHOST_ENABLE=1`

You can configure a remote backend via this environment variable. Either a remote PHP-FPM server or any kind of service via `http` or `https` reverse proxy.
You can configure a remote backend via this environment variable. Either a remote PHP-FPM server or any kind of service via `http`, `https`, `ws`, or `wss` reverse proxy (where `ws` and `wss` are for websocket backends).

### String format

Expand All @@ -368,7 +368,7 @@ The backend environment variable supports two different formats.
With the direct configuration you set everything explicitly via this environment variable and nothing else is required.

* **`<type>`**: `phpfpm` or `rproxy`
* **`<protocol>`**: `tcp`, `http` or `https`
* **`<protocol>`**: `tcp`, `http`, `https`, `ws` or `wss`
* **`<host>`**: the address of upstream host to send requests to (`hostname`, `IPv4` or `IPv6`).
* **`<port>`**: the port of the upstream host to send requests to

Expand All @@ -377,6 +377,8 @@ With the direct configuration you set everything explicitly via this environment
MAIN_VHOST_BACKEND=conf:phpfpm:tcp:10.0.0.1:9000
MAIN_VHOST_BACKEND=conf:rproxy:http:10.0.0.1:3000
MAIN_VHOST_BACKEND=conf:rproxy:https:10.0.0.1:3000
MAIN_VHOST_BACKEND=conf:rproxy:ws:10.0.0.1:3000
MAIN_VHOST_BACKEND=conf:rproxy:wss:10.0.0.1:3000
```

When specifying `phpfpm`, the vhost will also automatically be configured for serving PHP files. (including `index.php` for its directory index).
Expand Down
88 changes: 86 additions & 2 deletions doc/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
3. [Serve PHP files with PHP-FPM and sync local permissions](#-serve-php-files-with-php-fpm-and-sync-local-permissions)
4. [Serve PHP files with PHP-FPM over HTTPS](#-serve-php-files-with-php-fpm-over-https)
5. [Act as a Reverse Proxy for NodeJS](#-act-as-a-reverse-proxy-for-nodejs)
6. [Fully functional LEMP stack with Mass vhosts](#-fully-functional-lemp-stack-with-mass-vhosts)
7. [Docker Compose](#-docker-compose)
6. [Act as a Reverse Proxy for Websocket](#-act-as-a-reverse-proxy-for-websocket)
7. [Fully functional LEMP stack with Mass vhosts](#-fully-functional-lemp-stack-with-mass-vhosts)
8. [Docker Compose](#-docker-compose)



Expand Down Expand Up @@ -237,6 +238,89 @@ The following example proxies all HTTP requests to a NodeJS remote backend. You



## 💡 Act as a Reverse Proxy for Websocket

The following example proxies all HTTP requests to a Websocket remote backend. You could also enable SSL on the webserver in order to access the websocket backend via HTTPS.

* **Vhost:** main (default)
* **Backend:** Reverse Proxy (with websocket support)

> 🛈 No files need to be mounted into the webserver, as content is coming from the websocket server.

1. Create a websocket server application
```bash
# Create source directory
mkdir -p src

# websocket server application
cat << EOF > src/index.js
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 3000 });
wss.on("connection", (ws) => {
ws.send("hello client, you are connected to me");
ws.on("message", (message) => {
console.log("New message from client: %s", message);
});
});
console.log("WebSocket server ready at localhost:3000");
EOF

# package.json
cat << EOF > src/package.json
{
"name": "node-websocket-example",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"ws": "^7.5.1"
}
}
EOF

# Startup script
cat << EOF > src/start.sh
#!/bin/sh
npm install
node index.js
EOF
```
2. Start the Websocket server container
```bash
docker run -d -it \
--name websocket \
-v $(pwd)/src:/app \
-w /app \
node:19-alpine sh start.sh
```
3. Start Reverse Proxy
```bash
docker run -d -it \
-p 80:80 \
-e MAIN_VHOST_BACKEND='conf:rproxy:ws:websocket:3000' \
--link websocket \
devilbox/apache-2.4
```
4. Verify
```bash
# On your host system
npm install -g wscat
wscat --connect localhost

Connected (press CTRL+C to quit)
< hello client, you are connected to me
>
```



## 💡 Fully functional LEMP stack with Mass vhosts

The following example creates a dynamic setup. Each time you create a new project directory below `www/`, a new virtual host is being created.
Expand Down
4 changes: 3 additions & 1 deletion doc/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ Reverse Proxies are configured in a similar way to how PHP-FPM is setup as a rem
```bash
MAIN_VHOST_BACKEND:conf:rproxy:<protocol>:<server-addr>:<server-port>
```
Where `<procotol>` can by one of `http` or `https` (depending what your backend provides. `<server-addr>` and `<serer-port>` specify the hostname, IPv4 or IPv6 address of your upstream server, followed by its TCP port.
Where `<procotol>` can by one of `http`, `https`, `ws` or `wss` (depending what your backend provides. `<server-addr>` and `<serer-port>` specify the hostname, IPv4 or IPv6 address of your upstream server, followed by its TCP port.

**Note:** When specifying `ws` or `wss`, the webserver will automatically be configured to be capable of communicating with web sockets.



Expand Down
Loading