JFrog already provides extensive reverse proxy support for multiple uses of Artifactory. The application even has a built-in Reverse Proxy Configuration Generator. Nevertheless, if you’d like to use HAProxy with Artifactory, the following instructions and Artifactory Docker repository configuration examples – one for a single instance and the other for a cluster with two nodes – may help you in your efforts.
When you’re configuring a reverse proxy to work with Artifactory as a Docker registry, you can choose one of two options: In the configuration below, although we’ll show you how to work with a self-signed SSL certificate, be aware that you can also use a signed publicly trusted CA certificate. 1. First, create a self-signed certificate for your HAProxy: HAProxy TLS Termination
Certificate Generation
To begin, you'll need to generate a private key and a self-signed certificate for HAProxy to use. The following commands will create the necessary files:
openssl genrsa -out /etc/ssl/private/server.key mkdir /etc/ssl/csr openssl req -new -key /etc/ssl/private/server.key -out /etc/ssl/csr/server.csr openssl x509 -req -days 365 -in /etc/ssl/csr/server.csr -signkey /etc/ssl/private/server.key -out /etc/ssl/certs/server.crt cat /etc/ssl/certs/server.crt /etc/ssl/private/server.key > /etc/ssl/certs/server.bundle.pem
HAProxy Configuration
These instructions assume you already have a standard HTTP frontend configured in HAProxy. All changes are made in the /etc/haproxy/haproxy.cfg file.
Disable SSLv3
Due to security vulnerabilities like the POODLE attack, it's recommended to disable SSLv3. To do this globally, add the following line to the global section of your configuration file:
global
...
ssl-default-bind-options no-sslv3
Create an HTTPS Frontend
Next, create a new frontend to handle HTTPS traffic. This configuration tells HAProxy to listen for SSL/TLS connections and use the certificate you generated.
frontend web-https
bind public_ip:443 ssl crt /etc/ssl/certs/server.bundle.pem
reqadd X-Forwarded-Proto:\ https
rspadd Strict-Transport-Security:\ max-age=31536000
default_backend www-backend
Here is a breakdown of the directives:
- bind public_ip:443 ssl crt ...: This tells HAProxy to listen for requests on port 443 for the specified public IP. The ssl crt parameter points to the location of your combined certificate and key file.
- reqadd X-Forwarded-Proto:\ https: This adds an X-Forwarded-Proto header to incoming requests.
- rspadd Strict-Transport-Security...: This adds a security policy header to responses to help prevent protocol downgrade attacks.
- default_backend www-backend: This specifies the default backend server pool to forward requests to.
No changes are needed for your existing backend section.
Optional: Force HTTPS Redirection
If you want to redirect all HTTP traffic to HTTPS, add the following line to your existing HTTP frontend or backend section. The example uses the www-backend section.
redirect scheme https if !{ ssl_fc }
Restart HAProxy
After saving your configuration changes, restart the HAProxy service to apply them:
service haproxy restart
2. Copy the code and paste the code below into the /etc/haproxy/haproxy.cfg file. Note: This is an example for a Docker virtual repository using the Port Method for a single Artifactory instance: Global log <Machine_IP> local0 chroot /var/lib/haproxy maxconn 4096 user haproxy group haproxy daemon tune.ssl.default-dh-param 2048 stats socket /run/haproxy/admin.sock mode 660 level admin
Defaults
log global mode http option httplog option dontlognull option redispatch option forwardfor option http-server-close maxconn 4000 timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http
Frontend normal
bind *:80
bind *:443 ssl crt /etc/ssl/certs/server.bundle.pem
mode http
option forwardfor
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
option forwardfor header X-Real-IP
default_backend normal
Note: If you only need to access docker-dev-local2, then skip the following boxed section. However, while configuring the docker-virtual repository, you can select docker-dev-local2 as your Default Deployment Repository to store the images:
bind *:<Docker_Virtual_Port> ssl crt /etc/ssl/certs/server.bundle.pem
mode http
option forwardfor
option forwardfor header X-Real-IP
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
default_backend normal
Backend normal mode http server <Public_Server_Name> <Machine_IP>:<Port>
Note: The code snippet below is a baseline for an HA cluster, as well as a Docker setup. Use it to enable HAProxy balancing of your Artifactory nodes:
# haproxy server configuration # version 1.0 # History # ————————————————————————— # Features enabled by this configuration # HA configuration # port 80, 443 Artifactory GUI/API # # This uses ports to distinguish artifactory docker repositories # port 443 docker-virtual (v2) docker v1 is redirected to docker-dev-local. # port 5001 docker-prod-local (v1); docker-prod-local2 (v2) # port 5002 docker-dev-local (v1); docker-dev-local2 (v2) # # Edit this file with required information enclosed in <…> # 1. certificate and key # 2. artifactory-host # 3 replace the port numbers if needed # —————————————————————————-
Global log 127.0.0.1 local0 chroot /var/lib/haproxy maxconn 4096 user haproxy group haproxy daemon tune.ssl.default-dh-param 2048 stats socket /run/haproxy/admin.sock mode 660 level admin
Defaults log global mode http option httplog option dontlognull option redispatch option forwardfor option http-server-close maxconn 4000 timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http
Frontend normal bind *:80
bind *:443 ssl crt </etc/ssl/certs/server.bundle.pem>
mode http
option forwardfor
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker-virtual/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
option forwardfor header X-Real-IP
default_backend normal
Note: If you only need to access docker-dev-local2, then skip the following boxed section. However, while configuring the docker-virtual repository, you can select docker-dev-local2 as your Default Deployment Repository to store the images. bind *:5000 ssl crt </etc/ssl/certs/server.bundle.pem>
mode http
option forwardfor
option forwardfor header X-Real-IP
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker-remote/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
default_backend normal
Note: If you only need to access docker-dev-local2, then skip the following boxed section. bind *:5001 ssl crt </etc/ssl/certs/server.bundle.pem>
mode http
option forwardfor
option forwardfor header X-Real-IP
reqirep ^([^ :]*) /v1(.*$) 1 /artifactory/api/docker/docker-prod-local/v12
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker-prod-local2/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
default_backend normal
Note: If you only need to access docker-dev-local2, then skip the following boxed section. However, while configuring the docker-virtual repository, you can select docker-dev-local2 as your Default Deployment Repository to store the images. bind *:5002 ssl crt </etc/ssl/certs/server.bundle.pem>
mode http
option forwardfor
option forwardfor header X-Real-IP
reqirep ^([^ :]*) /v1(.*$) 1 /artifactory/api/docker/docker-dev-local/v12
reqirep ^([^ :]*) /v2(.*$) 1 /artifactory/api/docker/docker-dev-local2/v22
reqadd X-Forwarded-Proto: https if { ssl_fc }
default_backend normal
# Artifactory Non HA Configuration
# i.e server artifactory 198.168.1.206:8081
#
Backend normal
mode http
server <artifactory-host> <artifactory-host ip address>:<artifactory-host port>
#
# Artifactory HA Configuration
# Using default failover interval – rise = 2; fall =3 3; interval – 2 seconds
#backend normal
# mode http
# balance roundrobin
# option httpchk OPTIONS /
# option forwardfor
# option http-server-close # Recommended for closing connections cleanly
# --- Session Persistence Configuration --- #
# Store the cookie value and the server_id in the table.
# Look up its value in the stick-table and route to the stored server_id.
# stick-table type string size 1m expire 3h store server_id
# stick store-response set-cookie(JSESSIONID)
# stick on cookie(JSESSIONID)
# server <artifactory-host-ha1> <artifactory-host-ha1_ip>:<artifactory-port> check
# server <artifactory-host-ha2> <artifactory-host-ha2_ip>:<artifactory-port> check
1. Restart HAProxy: $sudo /etc/init.d/haproxy restart 2. Add the following to the /etc/hosts file: <Machine_IP> <Public_Server_Name>
Note: In production environments, use your DNS configuration, as the hosts file is typically used only for local testing. 3. Information on how to use a self-signed certificate with your Docker client can be found here . If you’d like to avoid using any certificates, add the following to your /etc/default/docker file, which will configure Docker to work with an insecure registry: DOCKER_OPTS=” –insecure-registry <Public_Server_Name>:<Repository_Port>“
4. Restart Docker: $sudo systemctl daemon-reload $sudo systemctl restart docker
Note: $ systemctl was used in the example above due to the use of Ubuntu 16.04 (which uses systemd).
You should now be able to execute $docker login and pulls to/pushes from Artifactory.
More information on how to get started with Artifactory Docker registries is available here.