kamal icon indicating copy to clipboard operation
kamal copied to clipboard

Kamal Proxy cannot be run on port other than 80/443

Open aarroisi opened this issue 1 year ago • 5 comments

In Kamal 1, I used host_port to specify in which port traefik will be run. It worked well. Now I'm trying to migrate to Kamal 2 and I change it to use app_port like so:

...
proxy:
  host: <%= ENV['HOST_RULE'] %>
  app_port: 8001
  healthcheck:
    path: /api/test/
    interval: 5
    timeout: 12
...

But when I run kamal deploy, it shows an error like this: docker: Error response from daemon: container f0af1c4f712bdb6905f707cf2f7dc6f8981d9122372f0cbb1b2a9b1f6327f6fd: endpoint join on GW Network failed: driver failed programming external connectivity on endpoint gateway_53bcdfbd02e1 (19dacb3d01219d4f82dcfc1413fb5f8e69c9deca92ac025666daf779df40c7f0): failed to bind port 0.0.0.0:80/tcp: Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use.

It seems like kamal-proxy still tries to bind to port 80, even though I specify it to run on port 8001.

I have tried many things:

  • Adding to env > clear > KAMAL_PROXY_HTTP_PORT: 8001
  • Running export KAMAL_PROXY_HTTP_PORT=8001 before kamal deploy

Still tries to bind to port 80.

aarroisi avatar Sep 27 '24 16:09 aarroisi

app_port doesn't change kamal-proxy's port. Instead, that is for your application container's port that it is going to try and connect to. For example, a default Rails app using Puma will be hosted on port 3000, so you would set the app_port to 3000 to tell kamal-proxy that it needs to connect to the application on port 3000 instead of the default port 80 of the application port.

kobaltz avatar Sep 27 '24 17:09 kobaltz

app_port doesn't change kamal-proxy's port. Instead, that is for your application container's port that it is going to try and connect to. For example, a default Rails app using Puma will be hosted on port 3000, so you would set the app_port to 3000 to tell kamal-proxy that it needs to connect to the application on port 3000 instead of the default port 80 of the application port.

Ah, I thought it would be directly analogous to the previous "host_port" on Kamal 1. So now it is not possible to change on which port the kamal-proxy is running?

aarroisi avatar Sep 27 '24 17:09 aarroisi

I'm not sure as I don't have any experience with trying to change the kamal-proxy that it's listening on. However, I would probably say that you're on the right path with the KAMAL_PROXY_HTTP_PORT as described in their README.

kobaltz avatar Sep 27 '24 17:09 kobaltz

Thanks for the reply. It really breaks my flow since I still need to run nginx/Caddy as the webserver and only only use kamal-proxy (traefik before) for deployment purpose. I used to run traefik on port other than 80/443 and let nginx/Caddy handle that.

aarroisi avatar Sep 28 '24 07:09 aarroisi

Thanks for the reply. It really breaks my flow since I still need to run nginx/Caddy as the webserver and only only use kamal-proxy (traefik before) for deployment purpose. I used to run traefik on port other than 80/443 and let nginx/Caddy handle that.

me too

andresribeiro avatar Sep 28 '24 12:09 andresribeiro

It turns out, we can configure this based on this PR (https://github.com/basecamp/kamal/pull/974), put inside pre-deploy hook. I guess this solves my problem.

aarroisi avatar Sep 29 '24 18:09 aarroisi

@aarroisi is right, but kamal documentation is pretty bad

first, the port that your app is using inside the container. Next uses 3000. so on config/deploy.yml you just

proxy:
  app_port: 3000

now you need to tell kamal which port its proxy should run, so type on your terminal and run

kamal proxy boot_config set --http-port 4444 --https-port 4445

--https-port seems to be required

hope it helps you save your time.

andresribeiro avatar Oct 01 '24 23:10 andresribeiro

This approach doesn't work for me because it modifies the .kamal/proxy/options file, but the command that Kamal runs on the remote server is:

docker container start kamal-proxy || docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --volume kamal-proxy-config:/home/kamal-proxy/.config/kamal-proxy $(cat .kamal/proxy/options || echo "--publish 80:80 --publish 443:443 --log-opt max-size=10m") basecamp/kamal-proxy:v0.8.2

This is effectively the same as running docker container start kamal-proxy, which fails with the following error:

Error response from daemon: driver failed programming external connectivity on endpoint kamal-proxy (fc557acc20a10afd7c212313d96b0bc2899112793d3614fef36d88840fdb05e4): failed to bind port 0.0.0.0:80/tcp: Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
Error: failed to start containers: kamal-proxy

I simply need to change the port configuration. How can I achieve this?

My .kamal/proxy/options is:

--publish 8080:8080 --log-opt max-size=10m

pioz avatar Nov 19 '24 18:11 pioz

@aarroisi is right, but kamal documentation is pretty bad

first, the port that your app is using inside the container. Next uses 3000. so on config/deploy.yml you just

proxy:
  app_port: 3000

now you need to tell kamal which port its proxy should run, so type on your terminal and run

kamal proxy boot_config set --http-port 4444 --https-port 4445

--https-port seems to be required

hope it helps you save your time.

Final step will be kamal proxy reboot

hdupadhyay avatar Dec 10 '24 10:12 hdupadhyay

Hello, i have the same problem i upgrade my rails 7.2 app onto rails 8 and i have this kamal config alongside with dockerfile

service: assnj
image: adammusa/assnj

servers:
  web:
    hosts:
      - my_ip_address

registry:
  username: adammusa
  password:
    - KAMAL_REGISTRY_PASSWORD
    
proxy:
  ssl: true
  app_port: 3000
  host: my_host
  
env:
  clear:
    RAILS_SERVE_STATIC_FILES: true
    RAILS_LOG_TO_STDOUT: true
    RAIL_LOG_LEVEL: debug
  secret:
    - RAILS_MASTER_KEY
    - MYSQL_ROOT_PASSWORD
    - DB_HOST

builder:
  arch: amd64

asset_path: /rails/public/assets

volumes:
  - "assnj_storage:/rails/storage"

accessories:
  db:
    image: mysql:8.0
    host: my_ip_address
    port: "127.0.0.1:3306:3306"
    env:
      clear:
        DB_HOST: assnj-db
        MYSQL_ROOT_HOST: '%'
      secret:
        - MYSQL_ROOT_PASSWORD
    files:
      - db/production.sql:/docker-entrypoint-initdb.d/setup.sql
    directories:
      - data:/var/lib/mysql

and

# syntax = docker/dockerfile:1

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.6
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base

# Rails app lives here
WORKDIR /rails

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle" \
    BUNDLE_WITHOUT="development"


# Throw-away build stage to reduce size of final image
FROM base as build

# Install packages needed to build gems
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential default-libmysqlclient-dev git curl libvips pkg-config

# Install application gems
COPY Gemfile Gemfile.lock ./

# Install node modules
ARG NODE_VERSION=20.11.0
ARG YARN_VERSION=1.22.19
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    npm install -g yarn@$YARN_VERSION && \
    rm -rf /tmp/node-build-master

RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

# Copy application code
COPY . .

# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/

# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile


# Final stage for app image
FROM base

# Install packages needed for deployment
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y curl default-mysql-client libvips && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails

# Run and own only the runtime files as a non-root user for security
# RUN useradd rails --create-home --shell /bin/bash && \
#     chown -R rails:rails db log storage tmp
# USER rails:rails
RUN groupadd --system --gid 1000 rails && \
    useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage tmp
USER 1000:1000
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start server via Thruster by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/thrust", "./bin/rails", "server"]

I EXPOSE 3000 in dockerfile to mach with app_port from deploy.yaml or EXPOSE 80 and kept the default app_port(80) for kamal proxy my still show me the 404 page of kamal proxy.

Screenshot 2024-12-12 at 01 35 10

kamal app logs

Screenshot 2024-12-12 at 01 37 22

kamal proxy logs

Screenshot 2024-12-12 at 01 38 35

kamal app details

Screenshot 2024-12-12 at 01 39 49

I need help please

AdamMusa avatar Dec 12 '24 06:12 AdamMusa

same issue

Bassem-Gh avatar Dec 30 '24 14:12 Bassem-Gh