feature/jenkins-proxy (#182)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/182 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
1
Jenkins/.gitignore
vendored
Normal file
1
Jenkins/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.generated
|
2
Jenkins/Jenkinsfile
vendored
2
Jenkins/Jenkinsfile
vendored
@@ -6,7 +6,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
dockerfile {
|
dockerfile {
|
||||||
filename 'Jenkins/agent/Dockerfile'
|
filename 'Jenkins/jenkins-agent/Dockerfile'
|
||||||
args """--user root --network ${params.AGENT_NETWORK}
|
args """--user root --network ${params.AGENT_NETWORK}
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock
|
--volume /var/run/docker.sock:/var/run/docker.sock
|
||||||
--memory=8g --cpus=${params.AGENT_CPUS}"""
|
--memory=8g --cpus=${params.AGENT_CPUS}"""
|
||||||
|
157
Jenkins/Makefile
157
Jenkins/Makefile
@@ -1,54 +1,169 @@
|
|||||||
DOCKER := docker
|
include .env
|
||||||
|
export
|
||||||
|
|
||||||
SOCKET := /var/run/docker.sock
|
SOCKET := /var/run/docker.sock
|
||||||
VOLUME := jenkins_home
|
VOLUME := jenkins_home
|
||||||
|
|
||||||
.PHONY: build run bash init-pw unprotected protected start stop rm purge
|
CERTBOT_CONF := $(PWD)/.generated/certbot/lib/conf
|
||||||
|
CERTBOT_WWW := $(PWD)/.generated/certbot/lib/www
|
||||||
|
CERTBOT_LOG := $(PWD)/.generated/certbot/log
|
||||||
|
NGINX_LOG := $(PWD)/.generated/certbot/nginx/log
|
||||||
|
|
||||||
# building the Jenkins image
|
.PHONY: provision \
|
||||||
|
build run bash init-pw unprotected protected start stop rm purge \
|
||||||
|
nginx-prepare nginx-proxy nginx-start nginx-letsencrypt-init nginx-letsencrypt-timer nginx-restart nginx-stop
|
||||||
|
|
||||||
|
## lists all documented targets
|
||||||
|
help:
|
||||||
|
@awk '/^##/ {sub(/^## /, "", $$0); desc=$$0; next} /^[a-zA-Z0-9][^:]*:/ { \
|
||||||
|
print "\033[1m" $$1 "\033[0m"; \
|
||||||
|
print " " desc "\n" \
|
||||||
|
}' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
## initially, run this once to provision te nginx
|
||||||
|
provision: nginx-prepare nginx-letsencrypt-init nginx-letsencrypt-timer nginx-start build start
|
||||||
|
|
||||||
|
## removes all generated files
|
||||||
|
clean: nginx-stop stop
|
||||||
|
rm -rf .generated/
|
||||||
|
|
||||||
|
## builds the Jenkins image
|
||||||
build:
|
build:
|
||||||
$(DOCKER) build -t jenkins-docker .
|
docker build -t jenkins-docker .
|
||||||
|
|
||||||
# initially running the Jenkins container
|
## manually running the Jenkins container
|
||||||
run:
|
run:
|
||||||
$(DOCKER) run --detach \
|
docker run --detach \
|
||||||
--dns 8.8.8.8 \
|
--dns 8.8.8.8 \
|
||||||
--network bridge \
|
--network bridge \
|
||||||
--publish 8080:8080 --publish 50000:50000 \
|
--publish 8090:8080 --publish 50000:50000 \
|
||||||
--volume $(SOCKET):/var/run/docker.sock \
|
--volume $(SOCKET):/var/run/docker.sock \
|
||||||
--volume $(VOLUME):/var/jenkins_home \
|
--volume $(VOLUME):/var/jenkins_home \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
--name jenkins jenkins-docker
|
--name jenkins jenkins-docker
|
||||||
|
|
||||||
# (re-) starts the Jenkins container
|
## manually starts the Jenkins container (again)
|
||||||
start:
|
start:
|
||||||
$(DOCKER) start jenkins
|
docker start jenkins
|
||||||
|
|
||||||
# opens a bash within the Jenkins container
|
## opens a bash within the Jenkins container
|
||||||
bash:
|
bash:
|
||||||
$(DOCKER) exec -it jenkins bash
|
docker exec -it jenkins bash
|
||||||
|
|
||||||
# prints the inital password of a newly setup Jenkins
|
## prints the initial password of a newly setup Jenkins
|
||||||
init-pw:
|
init-pw:
|
||||||
$(DOCKER) exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
|
docker exec -it jenkins sh -c '\
|
||||||
|
while [ ! -f /var/jenkins_home/secrets/initialAdminPassword ]; do \
|
||||||
|
sleep 1; \
|
||||||
|
done; \
|
||||||
|
cat /var/jenkins_home/secrets/initialAdminPassword \
|
||||||
|
'
|
||||||
|
|
||||||
# disables security for the Jenkins, allows login without credentials
|
## disables security for the Jenkins => allows login to Jenkins without credentials
|
||||||
unprotected:
|
unprotected:
|
||||||
docker exec -it jenkins sed -i 's|<useSecurity>true</useSecurity>|<useSecurity>false</useSecurity>|' /var/jenkins_home/config.xml
|
docker exec -it jenkins sed -i 's|<useSecurity>true</useSecurity>|<useSecurity>false</useSecurity>|' /var/jenkins_home/config.xml
|
||||||
docker exec -it jenkins grep useSecurity /var/jenkins_home/config.xml
|
docker exec -it jenkins grep useSecurity /var/jenkins_home/config.xml
|
||||||
|
|
||||||
# enables security for the Jenkins, requires login with credentials
|
## enables security for the Jenkins => Jenkins requires login with credentials
|
||||||
protected:
|
protected:
|
||||||
docker exec -it jenkins sed -i 's|<useSecurity>true</useSecurity>|<useSecurity>true</useSecurity>|' /var/jenkins_home/config.xml
|
docker exec -it jenkins sed -i 's|<useSecurity>true</useSecurity>|<useSecurity>true</useSecurity>|' /var/jenkins_home/config.xml
|
||||||
docker exec -it jenkins grep useSecurity /var/jenkins_home/config.xml
|
docker exec -it jenkins grep useSecurity /var/jenkins_home/config.xml
|
||||||
|
|
||||||
# stops the Jenkins container
|
## stops the Jenkins container
|
||||||
stop:
|
stop:
|
||||||
$(DOCKER) stop jenkins
|
docker stop jenkins
|
||||||
|
|
||||||
# removes the Jenkins container
|
## removes the Jenkins container
|
||||||
rm: stop
|
rm: stop
|
||||||
$(DOCKER) rm jenkins
|
docker rm jenkins
|
||||||
|
|
||||||
# purges the Jenkins volume (finally deletes the configuration)
|
## purges the Jenkins volume (finally deletes the configuration)
|
||||||
purge: rm
|
purge: rm
|
||||||
$(DOCKER) volume rm $(VOLUME)
|
docker volume rm $(VOLUME)
|
||||||
|
|
||||||
|
# (internal) generates the files for nginx-proxy and certbot
|
||||||
|
nginx-prepare:
|
||||||
|
mkdir -p $(CERTBOT_WWW) $(CERTBOT_LOG) $(CERTBOT_CONF)/live/$(SERVER_NAME) $(NGINX_LOG)
|
||||||
|
chmod 755 $(CERTBOT_WWW) $(CERTBOT_LOG) $(CERTBOT_CONF)/live/$(SERVER_NAME) $(NGINX_LOG)
|
||||||
|
sed -e 's/%SERVER_NAME/$(SERVER_NAME)/g' <nginx-proxy/nginx.conf >.generated/nginx.conf
|
||||||
|
cp nginx-proxy/options-ssl-nginx.conf $(CERTBOT_CONF)/options-ssl-nginx.conf
|
||||||
|
chmod 644 $(CERTBOT_CONF)/options-ssl-nginx.conf
|
||||||
|
test -f $(CERTBOT_CONF)/ssl-dhparams.pem || curl -o $(CERTBOT_CONF)/ssl-dhparams.pem \
|
||||||
|
https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem
|
||||||
|
chmod 644 $(CERTBOT_CONF)/ssl-dhparams.pem
|
||||||
|
openssl req -x509 -nodes -newkey rsa:2048 \
|
||||||
|
-keyout $(CERTBOT_CONF)/live/$(SERVER_NAME)/privkey.pem \
|
||||||
|
-out /$(CERTBOT_CONF)/live/$(SERVER_NAME)/fullchain.pem \
|
||||||
|
-subj "/CN=dummy"
|
||||||
|
|
||||||
|
## opens a bash within the Nginx-proxy container
|
||||||
|
nginx-bash:
|
||||||
|
docker exec -it nginx bash
|
||||||
|
|
||||||
|
# (internal) fetches an initial certificate from letsencrypt
|
||||||
|
nginx-letsencrypt-init: nginx-start
|
||||||
|
# wait for nginx actually running (could be improved)
|
||||||
|
@sleep 5
|
||||||
|
# delete the previous (dummy) config to avoid file creation with suffix -0001 etc.
|
||||||
|
rm -rf $(CERTBOT_CONF)/etc/letsencrypt/live/$(SERVER_NAME) \
|
||||||
|
$(CERTBOT_CONF)/etc/letsencrypt/archive/$(SERVER_NAME) \
|
||||||
|
$(CERTBOT_CONF)/etc/letsencrypt/renewal/$(SERVER_NAME).conf
|
||||||
|
# request the certificate via letsencrypt
|
||||||
|
docker run --rm \
|
||||||
|
-v $(CERTBOT_CONF):/etc/letsencrypt \
|
||||||
|
-v $(CERTBOT_WWW):/var/www/certbot \
|
||||||
|
-v $(CERTBOT_LOG):/var/log/letsencrypt \
|
||||||
|
certbot/certbot \
|
||||||
|
certonly --webroot --webroot-path /var/www/certbot \
|
||||||
|
--email $(EMAIL) --cert-name $(SERVER_NAME) \
|
||||||
|
-d $(SERVER_NAME) --rsa-key-size 4096 \
|
||||||
|
--agree-tos --force-renewal
|
||||||
|
# restart nginx
|
||||||
|
docker stop nginx || true
|
||||||
|
docker start nginx
|
||||||
|
|
||||||
|
## opens a shell in the letsencrypt certbot
|
||||||
|
nginx-letsencrypt-sh:
|
||||||
|
docker run -it --rm \
|
||||||
|
-v $(CERTBOT_CONF):/etc/letsencrypt \
|
||||||
|
-v $(CERTBOT_WWW):/var/www/certbot \
|
||||||
|
-v $(CERTBOT_LOG):/var/log/letsencrypt \
|
||||||
|
--entrypoint /bin/sh \
|
||||||
|
certbot/certbot
|
||||||
|
|
||||||
|
# (internal) installs the letsencrypt certbot timer for automatic renewal
|
||||||
|
nginx-letsencrypt-timer:
|
||||||
|
@mkdir -p $(HOME)/.config/systemd/user
|
||||||
|
@cp nginx-proxy/nginx-letsencrypt-renew.timer $(HOME)/.config/systemd/user/nginx-letsencrypt-renew.timer
|
||||||
|
@cp nginx-proxy/nginx-letsencrypt-renew.service $(HOME)/.config/systemd/user/nginx-letsencrypt-renew.service
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable --now nginx-letsencrypt-renew.timer
|
||||||
|
|
||||||
|
## renews the cert, if already renewable - this is also called from the timer
|
||||||
|
nginx-letsencrypt-renew:
|
||||||
|
docker run --rm \
|
||||||
|
-v $(CERTBOT_CONF):/etc/letsencrypt \
|
||||||
|
-v $(CERTBOT_WWW):/var/www/certbot \
|
||||||
|
-v $(CERTBOT_LOG):/var/log/letsencrypt \
|
||||||
|
certbot/certbot renew -q
|
||||||
|
|
||||||
|
## starts the nginx proxy server
|
||||||
|
nginx-start: nginx-stop
|
||||||
|
docker run -d --name nginx \
|
||||||
|
--publish 8080:80 \
|
||||||
|
--publish 8443:443 \
|
||||||
|
--network bridge \
|
||||||
|
-v $(CERTBOT_CONF):/etc/letsencrypt \
|
||||||
|
-v $(CERTBOT_WWW):/var/www/certbot \
|
||||||
|
-v $(NGINX_LOG):/var/log/nginx \
|
||||||
|
-v $(PWD)/.generated/nginx.conf:/etc/nginx/nginx.conf \
|
||||||
|
nginx
|
||||||
|
|
||||||
|
## restarts the nginx proxy server
|
||||||
|
nginx-restart: nginx-stop nginx-start
|
||||||
|
|
||||||
|
## stops the nginx proxy server
|
||||||
|
nginx-stop:
|
||||||
|
docker stop nginx || true
|
||||||
|
docker rm nginx || true
|
||||||
|
|
||||||
|
16
Jenkins/README.md
Normal file
16
Jenkins/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Jenkins Build+Test-Pipeline with NGINX HTTPS-Proxy and Letsencrypt
|
||||||
|
|
||||||
|
The scripts work in a Hostsharing Managed Docker environment.
|
||||||
|
|
||||||
|
Requires a .env file like this in the current directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
SERVER_NAME=jenkins.example.org
|
||||||
|
EMAIL=contact@example.org
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run `make provision` to initialize everything.
|
||||||
|
|
||||||
|
Run `make help` for more information.
|
||||||
|
|
||||||
|
WARNING: Provisioning does not really work yet, needs some manual restarts.
|
8
Jenkins/nginx-proxy/nginx-letsencrypt-renew.service
Normal file
8
Jenkins/nginx-proxy/nginx-letsencrypt-renew.service
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Renew Let's Encrypt certs via Make
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
WorkingDirectory=%h/hs.hsadmin.ng/Jenkins
|
||||||
|
ExecStart=/usr/bin/make nginx-letsencrypt-renew
|
||||||
|
|
11
Jenkins/nginx-proxy/nginx-letsencrypt-renew.timer
Normal file
11
Jenkins/nginx-proxy/nginx-letsencrypt-renew.timer
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Run cert renew Make target at ~5 AM daily
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=05:05
|
||||||
|
RandomizedDelaySec=20m
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
40
Jenkins/nginx-proxy/nginx.conf
Normal file
40
Jenkins/nginx-proxy/nginx.conf
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
events {}
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name %SERVER_NAME;
|
||||||
|
|
||||||
|
# directly answer initial certbot request
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
# forward all other HTTP-requests to HTTPS
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name %SERVER_NAME;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/%SERVER_NAME/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/%SERVER_NAME/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://%SERVER_NAME:8090;
|
||||||
|
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_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
7
Jenkins/nginx-proxy/options-ssl-nginx.conf
Normal file
7
Jenkins/nginx-proxy/options-ssl-nginx.conf
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
ssl_session_cache shared:le_nginx_SSL:1m;
|
||||||
|
ssl_session_timeout 1440m;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
|
||||||
|
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...";
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
Reference in New Issue
Block a user