Basic Localhost Reverse Proxy Question

1. My Caddy version (caddy version):

Unsure on exact caddy version. Currently running the abiosoft/caddy docker image through docker compose.

2. How I run Caddy:

Docker Compose with abiosoft/caddy image

a. System environment:

Debian (Specifically, the DietPi VirtualBox flavor)

b. Compose file:

version: '3.6'

services:
# Server  
  server:
    image: abiosoft/caddy
    container_name: caddy
    restart: always
    volumes:
    - ./Caddyfile:/etc/Caddyfile
    - ./.caddy:/root/.caddy
    ports:
    - 2015:2015
    - 80:80
    - 443:443

# Maria Database
  db:
    image: mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=REDACTED
    volumes:
      - /mnt/dietpi_userdata/docker-compose/mariadb:/var/lib/mysql
    restart: unless-stopped
    
# Database Management
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
    depends_on:
      - db

d. My complete Caddyfile or JSON config:

proxy localhost localhost:8080

3. The problem I’m having:

Pretty new to Caddy. Basically for now in my VM testing sandbox, I have a service, Adminer, on port 8080. What I would like to happen is I type “localhost” in my address bar and it takes me to “localhost:8080”. Eventually I would like to have it so that I enter “DOMAIN FOR SALE” and it takes me to the service. However, if I can’t get a basic localhost reverse proxy to work, I don’t think I can get a more advanced config to work :smiley:

4. Error messages and/or full log output:

The log output when I hit “docker-compose up” (apologies, it looks messy. Not sure how to properly format it):

Creating caddy                    ... done
Creating docker-compose_db_1 ... done
Creating docker-compose_adminer_1 ... done
Attaching to docker-compose_db_1, caddy, docker-compose_adminer_1
db_1       | 2020-03-16 17:17:46+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 1:10.4.12+maria~bionic started.
caddy      | Activating privacy features... 2020/03/16 17:17:45 [INFO][cache:0xc000032780] Started certificate maintenance routine
caddy      | 2020/03/16 17:17:46 [INFO][proxy] Obtain certificate
caddy      | 2020/03/16 17:17:46 [INFO] [proxy] acme: Obtaining bundled SAN certificate
caddy      | 2020/03/16 17:17:46 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 1/3; challenge=tls-alpn-01)
db_1       | 2020-03-16 17:17:47+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
db_1       | 2020-03-16 17:17:47+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 1:10.4.12+maria~bionic started.
adminer_1  | [Mon Mar 16 17:17:47 2020] PHP 7.4.3 Development Server (http://[::]:8080) started
caddy      | 2020/03/16 17:17:47 [INFO] [proxy] acme: Obtaining bundled SAN certificate
db_1       | 2020-03-16 17:17:47 0 [Note] mysqld (mysqld 10.4.12-MariaDB-1:10.4.12+maria~bionic) starting as process 1 ...
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Using Linux native AIO
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Uses event mutexes
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Number of pools: 1
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Using SSE2 crc32 instructions
db_1       | 2020-03-16 17:17:47 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
caddy      | 2020/03/16 17:17:47 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 2/3; challenge=tls-alpn-01)
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Completed initialization of buffer pool
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Creating shared tablespace for temporary tables
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Waiting for purge to start
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: 10.4.12 started; log sequence number 61197; transaction id 21
db_1       | 2020-03-16 17:17:47 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
db_1       | 2020-03-16 17:17:47 0 [Note] Plugin 'FEEDBACK' is disabled.
db_1       | 2020-03-16 17:17:47 0 [Note] Server socket created on IP: '::'.
db_1       | 2020-03-16 17:17:48 0 [Note] InnoDB: Buffer pool(s) load completed at 200316 17:17:48
db_1       | 2020-03-16 17:17:48 0 [Warning] 'proxies_priv' entry '@% root@1172df8fa6be' ignored in --skip-name-resolve mode.
db_1       | 2020-03-16 17:17:48 0 [Note] Reading of all Master_info entries succeeded
db_1       | 2020-03-16 17:17:48 0 [Note] Added new Master_info '' to hash table
db_1       | 2020-03-16 17:17:48 0 [Note] mysqld: ready for connections.
db_1       | Version: '10.4.12-MariaDB-1:10.4.12+maria~bionic'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution
caddy      | 2020/03/16 17:17:48 [INFO] [proxy] acme: Obtaining bundled SAN certificate
caddy      | 2020/03/16 17:17:48 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 3/3; challenge=tls-alpn-01)
caddy      | 2020/03/16 17:17:49 [INFO] [proxy] acme: Obtaining bundled SAN certificate
caddy      | 2020/03/16 17:17:49 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 1/3; challenge=http-01)
caddy      | 2020/03/16 17:17:50 [INFO] [proxy] acme: Obtaining bundled SAN certificate
caddy      | 2020/03/16 17:17:50 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 2/3; challenge=http-01)
caddy      | 2020/03/16 17:17:51 [INFO] [proxy] acme: Obtaining bundled SAN certificate
caddy      | 2020/03/16 17:17:52 [ERROR][proxy] failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url:  (attempt 3/3; challenge=http-01)
caddy      | 2020/03/16 17:17:53 failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "proxy": Domain name needs at least one dot, url: 
caddy      | exit status 1
caddy exited with code 1

5. What I already tried:

I’ve searched the forum, followed examples and tutorials on the Caddy documentation to no avail. I can provide more info if needed. Hopefully this is an easy fix. Thanks!

Use triple backticks for formatting. Put these ``` before and after your code block on their own lines.

I’ve gone ahead and edited it for you. (You were close, you only used one backtick instead of three)


Please read through https://caddyserver.com/v1/docs/caddyfile, it should explain to you how to structure your Caddyfile.

I think you’re looking for something like this:

localhost {
    proxy / localhost:8080
}

This will match requests to localhost, and proxy all requests (i.e. /) to localhost:8080.

When you want to use it with a real domain, I’d strongly recommend using a subdomain like service.mydomain.org instead of a subpath, like /service. Most services don’t handle being run in a subpath very well, and often any links in the site will point to the wrong place due to using absolute paths in link URLs.

Your config will likely look something like this:

service.mydomain.org {
    tls your@email.com

    proxy / localhost:8080 {
        transparent
    }
}

Edit: I noticed another issue. You won’t be able to use localhost in your Caddyfile when you run it in Docker like this, because nothing else is running inside the same container as Caddy. localhost points to the same container.

Since you’re using docker-compose, you’ll instead be using the name of the service you want to proxy to as the domain. docker-compose registers each service in Docker’s internal DNS server for you. So your proxy will look like this instead: proxy / adminer:8080

1 Like

Thanks for the reply @francislavoie!

I realize where I went wrong structure wise. I was zoning in on the proxy page of the documentation and thought all I needed was proxy from to…

My current Caddyfile is:

localhost {
    proxy / adminer:8080
}

After I restarted Docker, still no luck.I’ve entered both http://localhost and http://localhost/adminer with no luck. My apologies if the questions are really basic and clogging the forum. :sweat:

No worries! We’re here to help!

I think what’s going on is that just specifying localhost on its own without a port will actually default to port 2015. See https://caddyserver.com/v1/docs/http-caddyfile where it mentions:

localhost                # Host: localhost; Port: 2015

So instead, I think we want either localhost:80 or http://localhost.

Sorry for misleading you :sweat_smile:

For next time, you’ll notice that the Caddy logs will have said that it’s listening on port 2015 instead of port 80, which should be a red flag :triangular_flag_on_post:!

Ha! Works like a hot damn now :smiley:

For next time, you’ll notice that the Caddy logs will have said that it’s listening on port 2015 instead of port 80, which should be a red flag :triangular_flag_on_post:!

The logs that you are referring to, would they be, in my case, what is displayed after I start Docker? Or does Caddy keep logs somewhere else?

Once again, thanks for your help, it is much appreciated :).

1 Like

The easiest way for your setup is to run docker-compose logs caddy to get the stdout output from the caddy container.

There’s also the log and access directives that can write the logs to file. If you use these, you’ll want to set up volumes to persist them to your host machine.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.