Compare commits

...

20 Commits

Author SHA1 Message Date
38a75be17a build on every push
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 48s
Container Publish / build-image (arm64) (push) Successful in 30s
Container Publish / update docker manifest (push) Successful in 9s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest) (push) Successful in 7s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest-php74) (push) Successful in 5s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest-php74) (push) Successful in 7s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest) (push) Successful in 15s
2025-10-02 22:50:52 +02:00
6de6a7e1c0 build on wednesday 2025-10-02 22:50:06 +02:00
c5bde2c411 skip docker cache 2025-10-02 22:49:49 +02:00
349a8a05e1 better vulnscan message 2025-10-02 22:48:53 +02:00
4fb6d71a77 start SSH only if enables
Some checks failed
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (arm64) (push) Successful in 11s
Container Publish / build-image (amd64) (push) Successful in 46s
Container Publish / update docker manifest (push) Successful in 9s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest) (push) Failing after 6s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest-php74) (push) Successful in 4s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest) (push) Failing after 7s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest-php74) (push) Successful in 15s
2025-08-04 11:43:13 +02:00
1af3f39722 hourly stats
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (arm64) (push) Successful in 13s
Container Publish / build-image (amd64) (push) Successful in 20s
Container Publish / update docker manifest (push) Successful in 12s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest) (push) Successful in 9s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest-php74) (push) Successful in 5s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest) (push) Successful in 16s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest-php74) (push) Successful in 17s
2025-08-01 14:30:44 +02:00
b53adb411c fix log name
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 19s
Container Publish / build-image (arm64) (push) Successful in 21s
Container Publish / update docker manifest (push) Successful in 10s
2025-08-01 08:11:38 +02:00
2da562ffcb fix #5: added DISABLE_WEBDAV flag
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (arm64) (push) Successful in 20s
Container Publish / build-image (amd64) (push) Successful in 3m21s
Container Publish / update docker manifest (push) Successful in 53s
2025-07-31 20:16:35 +02:00
0f78f4cebc use real IPs instead of docker ones (PHP 7.4)
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (arm64) (push) Successful in 11s
Container Publish / build-image (amd64) (push) Successful in 12s
Container Publish / update docker manifest (push) Successful in 10s
2025-07-31 17:29:31 +02:00
5de2b67275 fix log path in php7.4
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (arm64) (push) Successful in 11s
Container Publish / build-image (amd64) (push) Successful in 17s
Container Publish / update docker manifest (push) Successful in 9s
2025-07-31 17:22:27 +02:00
1857bd66c5 fix chmod if dir not exists in php 7.4 2025-07-31 17:20:31 +02:00
671bfc5a99 fix #10: use real IPs instead of docker ones
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 20s
Container Publish / build-image (arm64) (push) Successful in 19s
Container Publish / update docker manifest (push) Successful in 10s
2025-07-31 16:38:06 +02:00
dfdea84bf7 fix #9: stats doesn't need a separate server
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 20s
Container Publish / build-image (arm64) (push) Successful in 19s
Container Publish / update docker manifest (push) Successful in 9s
2025-07-31 16:16:02 +02:00
9a838df27c FIX #7: ignore healthchecks entries
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 19s
Container Publish / build-image (arm64) (push) Successful in 21s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest) (push) Successful in 23s
Vulnerability Scan / Daily Vulnerability Scan (amd64, latest-php74) (push) Successful in 23s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest) (push) Successful in 7s
Vulnerability Scan / Daily Vulnerability Scan (arm64, latest-php74) (push) Successful in 6s
Container Publish / update docker manifest (push) Successful in 10s
2025-07-31 15:44:14 +02:00
b8c4e51fbe FIX #4: added DISABLE_STATS flag and moved stats refresh in a dedicated script 2025-07-31 15:43:47 +02:00
8d534bfd9b fix #7: goaccess ignore localhost 2025-07-31 15:34:25 +02:00
7323fab689 docs 2025-07-31 15:31:01 +02:00
796341c7a0 FIX #2: added DISABLE_SFTP flag 2025-07-31 15:26:45 +02:00
21f3e27039 build and publich every master commit, no need for tag
All checks were successful
Container Publish / on-success-skip (push) Has been skipped
Container Publish / build-image (amd64) (push) Successful in 19s
Container Publish / build-image (arm64) (push) Successful in 20s
Container Publish / update docker manifest (push) Successful in 9s
2025-07-31 15:21:34 +02:00
092e9d552b fix #11: added DISABLE_WEBROOT_CHOWN 2025-07-31 15:19:37 +02:00
17 changed files with 131 additions and 64 deletions

View File

@@ -7,10 +7,8 @@ env:
on: on:
push: push:
tags:
- '*'
schedule: schedule:
- cron: "0 12 3 * *" - cron: "0 12 * * 3"
workflow_dispatch: workflow_dispatch:
workflow_call: workflow_call:
workflow_run: workflow_run:
@@ -48,7 +46,7 @@ jobs:
run: | run: |
docker build \ docker build \
--tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }} \ --tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }} \
--platform linux/${{ matrix.arch }} -f Dockerfile . --platform linux/${{ matrix.arch }} --no-cache -f Dockerfile .
docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }} docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }}

View File

@@ -39,7 +39,7 @@ jobs:
run: | run: |
docker build \ docker build \
--tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-php74-${{ matrix.arch }} \ --tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-php74-${{ matrix.arch }} \
--platform linux/${{ matrix.arch }} -f Dockerfile-php74 . --platform linux/${{ matrix.arch }} --no-cache -f Dockerfile-php74 .
docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-php74-${{ matrix.arch }} docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-php74-${{ matrix.arch }}

View File

@@ -62,4 +62,4 @@ jobs:
token: ${{ secrets.TELEGRAM_TOKEN }} token: ${{ secrets.TELEGRAM_TOKEN }}
format: markdown format: markdown
message: | message: |
Found **${{ steps.vulncount.outputs.VULNCOUNT }}** vulnerabilities in `${{ github.repository }}` Found **${{ steps.vulncount.outputs.VULNCOUNT }}** vulnerabilities in `${{ env.REGISTRY }}/${{ env.REPOSITORY }}:${{ matrix.tag }}`

View File

@@ -12,29 +12,41 @@ services:
image: docker.asperti.com/paspo/webserver-nginx image: docker.asperti.com/paspo/webserver-nginx
ports: ports:
- 8888:80 # web server - 8888:80 # web server
- 8889:8081 # stats page
- 8890:8080 # webdav access - 8890:8080 # webdav access
- 2222:22 # sftp access - 2222:22 # sftp access
volumes: volumes:
- ./data:/data - ./data:/data
- ./ssh:/ssh # add authorized_keys file here
- ./extra_nginx.conf:/etc/nginx/custom.d/extra.conf # optional - ./extra_nginx.conf:/etc/nginx/custom.d/extra.conf # optional
- ./htpasswd:/app/htpasswd # optional, for webdav auth
environment: environment:
LOG_DAYS: 14 # default 7 LOG_DAYS: 14 # default 7
WEBDAV_PORT: 8080 # default: 8080 WEBDAV_PORT: 8080 # default: 8080
STATS_PORT: 8081 # default: 8081 PHP: php84 # none (default), php82, php83, php84
PHP: php84 # none (default), php82, php83, php84 POSTSIZE: 256M # default: 256M
POSTSIZE: 256M # default: 256M PUID: 1000 # default: 1000
PUID: 1000 # default: 1000 PGID: 1000 # default: 1000
PGID: 1000 # default: 1000 USERNAME: theuser # default: theuser
USERNAME: theuser # default: theuser GROUPNAME: thegroup # default: thegroup
GROUPNAME: thegroup # default: thegroup TZ: Etc/UTC # default: Etc/UTC
TZ: Etc/UTC # default: Etc/UTC FPM_MAX_CHILDREN: 5 # default: 5
FPM_MAX_CHILDREN: 5 # default: 5 FPM_START_SERVERS: 1 # default: 1
FPM_START_SERVERS: 1 # default: 1 FPM_MIN_SPARE_SERVERS: 1 # default: 1
FPM_MIN_SPARE_SERVERS: 1 # default: 1 FPM_MAX_SPARE_SERVERS: 3 # default: 3
FPM_MAX_SPARE_SERVERS: 3 # default: 3 DISABLE_WEBROOT_CHOWN: 1 # default: 0
DISABLE_SFTP: 1 # default: 0
DISABLE_STATS: 1 # default: 0
DISABLE_STATS_HOURLY: 1 # default: 0
DISABLE_WEBDAV: 1 # default: 0
``` ```
The `/data/www` and `/data/logs` directories and their contents will be chowned to `$PUID:$PGID` and chmodded to `0755` for directories and `0644` for files at container start. The `/data/www` and `/data/logs` directories and their contents will be chowned to `$PUID:$PGID` and chmodded to `0755` for directories and `0644` for files at container start.
## data direcvtory layout
| directory | content |
|-----------|-----------------------------------------------|
| auth | htpasswd files for stats and webdav |
| logs | nginx access logs (logrotated) and error logs |
| ssh | host keys and authorized keys |
| stats | html statistical report |
| stats.db | internal statistical db |
| www | webroot |

View File

@@ -1,11 +0,0 @@
services:
web:
image: docker.asperti.com/paspo/webserver-nginx
ports:
- 8888:80
- 2222:22
volumes:
- ./www:/data/www
- ./ssh:/ssh # add authorized_keys file here
environment:
PHP: php84 # none (default), php82, php83, php84

View File

@@ -79,7 +79,9 @@ if [ -f /ssh/authorized_keys ] ; then
chown "${USERNAME}:${GROUPNAME}" /ssh/authorized_keys chown "${USERNAME}:${GROUPNAME}" /ssh/authorized_keys
fi fi
chmod 0700 "${WEBROOT}/.ssh" if [ -d "${PATH_WEBROOT}/.ssh" ] ; then
chmod 0700 "${PATH_WEBROOT}/.ssh"
fi
/usr/sbin/sshd -e /usr/sbin/sshd -e
cat > /etc/nginx/conf.d/user.conf <<EOF cat > /etc/nginx/conf.d/user.conf <<EOF

View File

@@ -9,7 +9,7 @@ worker_processes auto;
pcre_jit on; pcre_jit on;
# Configures default error logger. # Configures default error logger.
error_log /data/logs/nginx-error.log warn; error_log /var/log/nginx/error.log warn;
# Includes files with directives to load dynamic modules. # Includes files with directives to load dynamic modules.
include /etc/nginx/modules/*.conf; include /etc/nginx/modules/*.conf;
@@ -89,6 +89,10 @@ http {
'' close; '' close;
} }
# use real IPs instead of docker ones
set_real_ip_from 172.18.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Specifies the main log format. # Specifies the main log format.
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' log_format main '$remote_addr - $remote_user [$time_local] "$request" '
@@ -96,7 +100,7 @@ http {
'"$http_user_agent" "$http_x_forwarded_for"'; '"$http_user_agent" "$http_x_forwarded_for"';
# Sets the path, format, and configuration for a buffered log write. # Sets the path, format, and configuration for a buffered log write.
access_log /data/logs/nginx-access.log main; access_log /var/log/nginx/access.log main;
# Includes virtual hosts configs. # Includes virtual hosts configs.

View File

@@ -9,7 +9,6 @@ PATH_AUTH=${PATH_BASE}/auth
PATH_SSH_HOST=${PATH_BASE}/ssh PATH_SSH_HOST=${PATH_BASE}/ssh
WEBDAV_PORT=${WEBDAV_PORT:-8080} WEBDAV_PORT=${WEBDAV_PORT:-8080}
STATS_PORT=${STATS_PORT:-8081}
LOG_DAYS=${LOG_DAYS:-7} LOG_DAYS=${LOG_DAYS:-7}
PHP=${PHP:-none} PHP=${PHP:-none}
@@ -24,6 +23,12 @@ FPM_START_SERVERS=${FPM_START_SERVERS:-1}
FPM_MIN_SPARE_SERVERS=${FPM_MIN_SPARE_SERVERS:-1} FPM_MIN_SPARE_SERVERS=${FPM_MIN_SPARE_SERVERS:-1}
FPM_MAX_SPARE_SERVERS=${FPM_MAX_SPARE_SERVERS:-3} FPM_MAX_SPARE_SERVERS=${FPM_MAX_SPARE_SERVERS:-3}
DISABLE_WEBROOT_CHOWN=${DISABLE_WEBROOT_CHOWN:-0}
DISABLE_SFTP=${DISABLE_SFTP:-0}
DISABLE_STATS=${DISABLE_STATS:-0}
DISABLE_STATS_HOURLY=${DISABLE_STATS_HOURLY:-0}
DISABLE_WEBDAV=${DISABLE_WEBDAV:-0}
export USERNAME export USERNAME
export GROUPNAME export GROUPNAME
export PATH_BASE export PATH_BASE
@@ -34,7 +39,6 @@ export PATH_LOGS
export PATH_AUTH export PATH_AUTH
export PATH_SSH_HOST export PATH_SSH_HOST
export WEBDAV_PORT export WEBDAV_PORT
export STATS_PORT
export POSTSIZE export POSTSIZE
export LOG_DAYS export LOG_DAYS
export PHP export PHP
@@ -46,6 +50,12 @@ export FPM_START_SERVERS
export FPM_MIN_SPARE_SERVERS export FPM_MIN_SPARE_SERVERS
export FPM_MAX_SPARE_SERVERS export FPM_MAX_SPARE_SERVERS
export DISABLE_WEBROOT_CHOWN
export DISABLE_SFTP
export DISABLE_STATS
export DISABLE_STATS_HOURLY
export DISABLE_WEBDAV
# run all scripts in order # run all scripts in order
run-parts /app/entrypoint.sh.d run-parts /app/entrypoint.sh.d
@@ -72,8 +82,10 @@ echo "# Starting cron"
crond -b crond -b
# start ssh # start ssh
echo "# Starting ssh" if [ "${DISABLE_SFTP}" -ne 1 ] ; then
/usr/sbin/sshd -e echo "# Starting ssh"
/usr/sbin/sshd -e
fi
# start nginx # start nginx
echo "# Starting nginx" echo "# Starting nginx"

View File

@@ -1,7 +1,12 @@
#!/bin/sh #!/bin/sh
echo "# chowning ${PATH_WEBROOT} to ${PUID}:${GROUPNAME}..." echo "# Started background chowning of ${PATH_WEBROOT} to ${USERNAME}:${GROUPNAME} (${PUID}:${PGID})..."
chown "${PUID}:${GROUPNAME}" "${PATH_WEBROOT}" -R if [ ${DISABLE_WEBROOT_CHOWN} -eq 1 ] ; then
echo chowning skipped because of DISABLE_WEBROOT_CHOWN
exit 0
fi
chown "${USERNAME}:${GROUPNAME}" "${PATH_WEBROOT}" -R
find "${PATH_WEBROOT}" -type d -exec chmod 0755 {} \; & find "${PATH_WEBROOT}" -type d -exec chmod 0755 {} \; &
find "${PATH_WEBROOT}" -type f -exec chmod 0644 {} \; & find "${PATH_WEBROOT}" -type f -exec chmod 0644 {} \; &

View File

@@ -15,10 +15,11 @@ ${PATH_LOGS}/nginx-access.log {
compress compress
delaycompress delaycompress
sharedscripts sharedscripts
nodateext
su ${USERNAME} ${GROUPNAME} su ${USERNAME} ${GROUPNAME}
postrotate postrotate
/usr/sbin/nginx -s reopen /usr/sbin/nginx -s reopen
nice -n 19 /usr/bin/goaccess ${PATH_LOGS}/nginx-access.log.1 --agent-list --anonymize-ip --real-os --output ${PATH_STATS}/index.html --log-format COMBINED --tz="${TZ}" --db-path=${PATH_STATSDB} --persist --restore nice -n 19 /app/stats.sh
endscript endscript
} }
EOF EOF

View File

@@ -1,5 +1,9 @@
#!/bin/sh #!/bin/sh
if [ ${DISABLE_SFTP} -eq 1 ] ; then
exit 0
fi
echo "# Configuring ssh" echo "# Configuring ssh"
# make sure directory exists # make sure directory exists
@@ -23,8 +27,7 @@ if [ -d "${PATH_WEBROOT}/.ssh" ] ; then
chmod 0700 "${PATH_WEBROOT}/.ssh" chmod 0700 "${PATH_WEBROOT}/.ssh"
fi fi
# configure sshd
cat >/etc/ssh/sshd_config.d/sshd.conf <<EOF cat >/etc/ssh/sshd_config.d/sshd.conf <<EOF
HostKey ${PATH_SSH_HOST}/ssh_host_rsa_key HostKey ${PATH_SSH_HOST}/ssh_host_rsa_key
HostKey ${PATH_SSH_HOST}/ssh_host_ecdsa_key HostKey ${PATH_SSH_HOST}/ssh_host_ecdsa_key

View File

@@ -1,5 +1,9 @@
#!/bin/sh #!/bin/sh
if [ ${DISABLE_STATS} -eq 1 ] ; then
exit 0
fi
echo "# Configuring stats" echo "# Configuring stats"
# make sure paths exists # make sure paths exists
@@ -8,26 +12,11 @@ touch "${PATH_AUTH}/stats"
chown -R "${USERNAME}:${GROUPNAME}" "${PATH_AUTH}" "${PATH_STATS}" "${PATH_STATSDB}" chown -R "${USERNAME}:${GROUPNAME}" "${PATH_AUTH}" "${PATH_STATS}" "${PATH_STATSDB}"
# stats endpoint # stats endpoint
cat > /etc/nginx/http.d/stats.conf <<EOF cat > /etc/nginx/local.d/stats.conf <<EOF
server { location ^~ /stats {
listen ${STATS_PORT} default_server;
listen [::]:${STATS_PORT} default_server;
root ${PATH_STATS}; root ${PATH_STATS};
location = / {
index index.html;
try_files /index.html =404;
}
location /index.html {
try_files /index.html =404;
}
location / {
return 404;
}
auth_basic "Restricted area"; auth_basic "Restricted area";
auth_basic_user_file ${PATH_AUTH}/stats; auth_basic_user_file ${PATH_AUTH}/stats;
try_files /index.html =404;
} }
EOF EOF

View File

@@ -0,0 +1,14 @@
#!/bin/sh
if [ ${DISABLE_STATS} -eq 1 ] ; then
exit 0
fi
if [ ${DISABLE_STATS_HOURLY} -eq 1 ] ; then
exit 0
fi
echo "# Configuring hourly stats"
# stats endpoint
ln -s /app/stats_hourly.sh /etc/periodic/hourly/stats

View File

@@ -1,5 +1,9 @@
#!/bin/sh #!/bin/sh
if [ ${DISABLE_WEBDAV} -eq 1 ] ; then
exit 0
fi
echo "# Configuring webdav" echo "# Configuring webdav"
cat > /etc/nginx/http.d/webdav.conf <<EOF cat > /etc/nginx/http.d/webdav.conf <<EOF

15
rootfs/app/stats.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
if [ "${DISABLE_STATS:-0}" -eq 1 ] ; then
exit 0
fi
PATH_BASE=/data
PATH_STATS=${PATH_BASE}/stats
PATH_STATSDB=${PATH_BASE}/stats.db
PATH_LOGS=${PATH_BASE}/logs
/usr/bin/goaccess "${PATH_LOGS}/nginx-access.log.1" \
--agent-list --anonymize-ip --real-os --exclude-ip 127.0.0.1 \
--output "${PATH_STATS}/index.html" --log-format COMBINED \
--tz="${TZ}" "--db-path=${PATH_STATSDB}" --persist --restore

15
rootfs/app/stats_hourly.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
if [ "${DISABLE_STATS:-0}" -eq 1 ] ; then
exit 0
fi
PATH_BASE=/data
PATH_STATS=${PATH_BASE}/stats
PATH_STATSDB=${PATH_BASE}/stats.db
PATH_LOGS=${PATH_BASE}/logs
/usr/bin/goaccess "${PATH_LOGS}/nginx-access.log" \
--agent-list --anonymize-ip --real-os --exclude-ip 127.0.0.1 \
--output "${PATH_STATS}/index.html" --log-format COMBINED \
--tz="${TZ}" "--db-path=${PATH_STATSDB}" --persist --restore

View File

@@ -85,6 +85,10 @@ http {
'' close; '' close;
} }
# use real IPs instead of docker ones
set_real_ip_from 172.18.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Specifies the main log format. # Specifies the main log format.
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' log_format main '$remote_addr - $remote_user [$time_local] "$request" '