Unable to push docker images to artifactory - nginx

I set up artifactory as a docker registry and am trying to push an image to it
docker push nginxLoadBalancer.mycompany.com/repo_name:image_name
This fails with the following error
The push refers to a repository [ nginxLoadBalancer.mycompany.com/repo_name] (len: 1)
unable to ping registry endpoint https://nginxLoadBalancer.mycompany.com/v0/
v2 ping attempt failed with error: Get https://nginxLoadBalancer.mycompany.com/v2/: Bad Request
v1 ping attempt failed with error: Get https://nginxLoadBalancer.mycompany.com/v1/_ping: Bad Request
This is my nginx conf
upstream artifactory_lb {
server mNginxLb.mycompany.com:8081;
server mNginxLb.mycompany.com backup;
}
log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/my-certs/myCert.pem;
ssl_certificate_key /etc/nginx/ssl/my-certs/myserver.key;
client_max_body_size 2048M;
location / {
proxy_set_header Host $host:$server_port;
proxy_pass http://artifactory_lb;
proxy_read_timeout 90;
}
access_log /var/log/nginx/access.log upstreamlog;
location /basic_status {
stub_status on;
allow all;
}
}
# Server configuration
server {
listen 2222 ssl;
server_name mNginxLb.mycompany.com;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
rewrite ^/(v1|v2)/(.*) /api/docker/my_local_repo_key/$1/$2;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
proxy_pass http://artifactory_lb;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
There are no errors in the nginx error log. What might be wrong?
I verfied that the SSL verification works fine with the set up. Do I need to set up authentication before I push images?
I also verified artifactory server is listening on port 2222
Update,
I added the following to the nginx configuration
location /v1 {
proxy_pass http://myNginxLb.company.com:8080/artifactory/api/docker/docker-local/v1;
}
With this it now gives a 405 - Not allowed error when trying to push to the repository

I fixed this by removing the location /v1 configuration and also changing proxy pass to point to the upstream servers

Related

Nginx only responding to 1 of multiple https servers

The problem I'm facing is that I have nginx configured for 2 HTTPS servers and 1 is responding and working correctly but the other one with a near identical server config is showing "connection refused".
System:
Description: Ubuntu 22.04 LTS
nginx version: nginx/1.18.0 (Ubuntu)
I am working with a default nginx.conf file and have unlinked the default sites-available entry and each server_name is a subdomain with its own SSL cert & key. When I check the access and error logs there are no entries describing why subdomain2 connection is refused, or even log entries showing a connection attempt was made. Both cert/key pairs were generated by the IT dept at a university and since 1 is working fine I have good reason to think both pairs are valid.
I'm no nginx expert but I've setup multiple subdomains like this on different systems with success and am not sure what's going on. I've double & triple checked the basic stuff like making sure a valid sym-link exists in sites-enabled, no errors show up on nginx restart or systemctl status, and obviously the machine itself is listening on 0.0.0.0:https per netstat output as well as subdomain1 working correctly. I've also verified that the proxy_pass destination works when I use subdomain1 to point to it (also verified with curl on the nginx host).
Let me know if there is any other information I can provide.
Any help is appreciated.
Thanks
/etc/nginx/sites-available/subdomain1:
server {
listen 443 ssl;
server_name subdomain1.base.edu;
ssl_certificate /path/server.crt;
ssl_certificate_key /path/server.key;
client_max_body_size 0;
add_header Strict-Transport-Security max-age=15768000;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
/etc/nginx/sites-available/subdomain2:
server {
listen 443 ssl;
server_name subdomain2.base.edu;
ssl_certificate /path/server.crt;
ssl_certificate_key /path/server.key;
location / {
proxy_pass http://127.0.0.1:10123;
}
}
UPDATE (nginx -T output)
user#host:/etc/nginx/sites-available$ sudo nginx -T
[sudo] password:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
.....
# configuration file /etc/nginx/sites-enabled/subdomain1.base.edu:
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name subdomain1.base.edu;
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name subdomain1.base.edu;
ssl_certificate /path/.ssl/server.crt;
ssl_certificate_key /path/.ssl/server.key;
client_max_body_size 0;
add_header Strict-Transport-Security max-age=15768000;
include /etc/nginx/sites-available/shinyapps;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
# configuration file /etc/nginx/sites-available/shinyapps:
location /5627 {
proxy_pass http://localhost:5627/;
proxy_redirect / $scheme://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
# configuration file /etc/nginx/sites-enabled/subdomain2.base.edu:
#
# bustalab1 domain to proxy localhost shiny apps
server {
listen 80;
server_name subdomain2.base.edu;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name subdomain2.base.edu;
ssl_certificate /path/.ssl/subdomain2.crt;
ssl_certificate_key /path/.ssl/subdomain2.key;
error_log /var/log/nginx/subdomain2_err.log debug;
access_log /var/log/nginx/subdomain2_acc.log;
location / {
proxy_pass http://127.0.0.1:10123;
}
}

How to configure nginx reverse proxy to use SECURE websockets upstream?

I want to use nginx as a reverse proxy for websocket connections.
Consider echo.websocket.org to be my backend websocket service. As a test client I use wscat from https://github.com/websockets/wscat.
What works:
client <-- ws --> backend:
wscat --connect ws://echo.websocket.org
client <-- wss -->: wscat --connect wss://echo.websocket.org
client <-- ws --> proxy <-- ws --> backend: wscat --connect ws://localhost with the following nginx configuration:
events {
}
http {
server {
listen 80;
location / {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
}
client <-- wss --> proxy <-- ws --> backend: wscat -n --connect wss://localhost with the following nginx configuration:
events {
}
http {
server {
listen 443 ssl;
ssl_certificate /pki/cert.pem;
ssl_certificate_key /pki/key.pem;
location / {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
}
What I want and what I need help with is configuring nginx to use secure websockets to connect to the backend. I want this configuration:
client <-- wss --> proxy <-- wss --> backend
I tried changing http://echo.websocket.org to https://echo.websocket.org without success. This leads to a 504 Gateway Timeout.
You need to use proxy_ssl_certificate and proxy_ssl_certificate_key as specified in Nginx Docs
This is my config upstream, server_name, ssl_certificate, HTTP 301:
server {
listen 80; # nginx 80
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
# Set correct content type. According to this:
# https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
# Current specification requires "text/plain" or no content header at all.
# It seems that "text/plain" is a safe option.
default_type "text/plain";
# This directory must be the same as in /etc/letsencrypt/cli.ini
# as "webroot-path" parameter. Also don't forget to set "authenticator" parameter
# there to "webroot".
# Do NOT use alias, use root! Target directory is located here:
# /var/www/common/letsencrypt/.well-known/acme-challenge/
root /var/www/html;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/***0***0.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/***0***0.ru/privkey.pem; # managed by Certbot
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name ***0***0.ru; # server name
location /sockjs-node/ {
proxy_pass http://node; # wep application
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://node;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /smpp {
rewrite /smpp(.*) /$1 break;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
proxy_pass http://smpp;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
upstream smpp {
server localhost:5001;
}
upstream node {
server localhost:5000;
}

NGinx forward websocket from 80 to websocket port

I am using Nginx as a web host and proxy for a websocket running on the same device listening on port 8888. Trying to find a way to have nginx listen on 80 and forward the websocket requests to the internal port. Without exposing a new port to the outside. Is this even possible?
UPDATE:
This is my current configuration:
error_log /var/log/nginx/error_log.log warn;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server localhost:8888;
}
server {
listen 80;
#listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html/EncoderAdmin;
# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
}
location /ws {
proxy_pass http://localhost:8888;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
When I try to connect to it with ws://[address]/ws I get:
WebSocket connection to 'ws://[address]/ws' failed: Error during WebSocket handshake: Unexpected response code: 400
Yes, it's possible assuming you can distinguish the normal HTTP requests and the socket ones.
The simplest solution is to match the socket uri with location, for example all the requests to /ws will be redirected to localhost:8888, any other url to localhost:8889. Here it is an example of configuration
server {
server_name _;
location /ws {
proxy_pass http://localhost:8888;
# this magic is needed for WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
proxy_pass http://localhost:8889;
}
}
You should also remember to bind the websocket server to localhost:8888 and not to 0.0.0.0:8888. This step is not needed but with it the original port is not exposed!

Configuring docker virtual repository in artifactory

I have a local docker repository and a remote docker repository , I created a virtual docker repository combining both. In order to access this repository from the client side, does this need to be added to the reverse proxy as well?
Here is the current reverse proxy configuration
upstream artifactory_lb {
server myserver.mycompany.com:8081 backup;
server myserver.mycompany.com:8081;
}
log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';
ssl_certificate /etc/nginx/ssl/multidomain_cert_files/mycert.pem;
ssl_certificate_key /etc/nginx/ssl/multidomain_cert_files/mykey.key;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4';
ssl_session_cache shared:SSL:10m;
server {
listen 80;
listen 443 ssl;
client_max_body_size 2048M;
location / {
proxy_set_header Host $host;
proxy_pass http://artifactory_lb;
proxy_read_timeout 90;
}
access_log /var/log/nginx/access.log upstreamlog;
location /basic_status {
stub_status on;
allow all;
}
}
# Server configuration
server {
listen 2222 ssl;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
rewrite ^/(v1|v2)/(.*) /api/docker/myrepo_images/$1/$2;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
allow all;s
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://artifactory_lb/artifactory/;
}
}
Yes. Docker registries are referenced by their host name, only. This means that you'll need two virtual hosts in your reverse proxy with different hostnames (use the server_name directive for that), mapping to different Artifactory repositories.
The following example config (shortened) should do the trick:
server {
listen 2222 ssl;
server_name local-repo.my-artifactory.com;
rewrite ^/(v1|v2)/(.*) /api/docker/myrepo_images/$1/$2;
# <insert remaining configuration directives here>
}
server {
listen 2222 ssl;
server_name virtual-repo.my-artifactory.com;
rewrite ^/(v1|v2)/(.*) /api/docker/myrepo_virtual/$1/$2;
# <insert remaining configuration directives here>
}
Now you should be able to access both registries using the regular docker commands:
$ docker pull virtual-repo.my-artifactory.com:2222/foo/bar:latest
$ docker pull local-repo.my-artifactory.com:2222/foo/bar:latest
$ docker push local-repo.my-artifactory.com:2222/foo/bar:latest

RoR 5.0.0 ActionCable wss WebSocket handshake: Unexpected response code: 301

Hello I'm trying to serve a simple chat using ror 5.0.0 beta (with puma)
working on production mode (in localhost there are no problems).
This is my Nginx configuration:
upstream websocket {
server 127.0.0.1:28080;
}
server {
listen 443;
server_name mydomain;
ssl_certificate ***/server.crt;
ssl_certificate_key ***/server.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers
HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/jenkins.access.log;
location / {
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;
proxy_pass http://localhost:3000;
proxy_read_timeout 90;
proxy_redirect http://localhost:3000 https://mydomain;
location /cable/{
proxy_pass http://websocket/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
break;
}
}
This is config/redis/cable.yml
production:
url: redis://localhost:6379/1
development:
url: redis://localhost:6379/2
test:
url: redis://localhost:6379/3
and config/environments/production.rb
# Action Cable endpoint configuration
config.action_cable.url = 'wss://mydomain/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = false
And this is the error i'm receiving:
application-[...].js:27 WebSocket connection to 'wss://mydomain/cable' failed: Error during WebSocket handshake: Unexpected response code: 301
Any tips? :) Thanks
I solved adding phusion passenger.
nginx config is now :
server{
listen 80;
passenger_enabled on;
passenger_app_env production;
passenger_ruby /../ruby-2.3.0/ruby;
root /path to application/public;
client_max_body_size 4G;
keepalive_timeout 10;
[...]
location /cable{
passenger_app_group_name websocket;
passenger_force_max_concurrent_requests_per_process 0;
}
}
You have to remove default folder config/redis/cable.yml and move that file to /config only.
For SSL just enable default ssl options and it will works .-)
Thanks everyone for the help
Your websocket URI is /cable/ and not /cable, so the latter will hit the location / block. Try:
location /cable {
rewrite ^/cable$ / break;
rewrite ^/cable(.*)$ $1 break;
proxy_pass http://websocket;
...
}
Also, not sure you need a break; in there. I presume the missing } between the two location blocks is just a typo in the question.
EDIT1: Added rewrite to restore correct upstream mapping.
EDIT2: Alternative solution is to explicitly rewrite /cable to /cable/ like this:
location = /cable { rewrite ^ /cable/ last; }
location /cable/ {
proxy_pass http://websocket/;
...
}
I spend almost 5 hours yesterday trying to solve this particular problem. I ended up using a separate domain for the websocket connection called ws.example.com as everything else resulted in a 301 redirect.
Here's is my nginx.conf file. I've removed the SSL parts, but you could just insert your own. Note that you need nginx 1.4+ as everything prior to this version doesn't support websocket proxying.
upstream socket {
server unix:/mysocket fail_timeout=0;
}
upstream websocket {
server 127.0.0.1:28080;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name ws.example.com;
access_log off;
# SSL configs here
location / {
proxy_pass http://websocket/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server {
listen 443 ssl;
server_name example.com;
# SSL configs here
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://socket;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I read somewhere that allowed_request_origins didn't work as expected so I went the safe way (until the bug is fixed) and turned the checker of completely using ActionCable.server.config.disable_request_forgery_protection = true.
Here's my cable.ru file for starting action cable.
require ::File.expand_path('../../config/environment', __FILE__)
Rails.application.eager_load!
require 'action_cable/process/logging'
Rails.logger.level = 0
ActionCable.server.config.disable_request_forgery_protection = true
run ActionCable.server
I'm also using the latest rails version from Github.
gem "rails", github: "rails/rails"

Resources