Skip to content

Instantly share code, notes, and snippets.

@adrianmejias
Last active January 11, 2023 07:49
Show Gist options
  • Save adrianmejias/0997f2b8a20715428f594a4798e034f5 to your computer and use it in GitHub Desktop.
Save adrianmejias/0997f2b8a20715428f594a4798e034f5 to your computer and use it in GitHub Desktop.
How to Enable SSL for Local Laravel Sail Development using Caddy and Docker
# file: config/caddy.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Authorized Domains
|--------------------------------------------------------------------------
|
| Domains that are authorized to be viewed through Caddy.
|
*/
'authorized' => [
'laravel.test',
// 'app.laravel.test',
],
];
# file: app/Http/Controllers/CaddyController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CaddyController extends Controller
{
/**
* Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
if (in_array($request->query('domain'), config('caddy.authorized'))) {
return response('Domain Authorized');
}
abort(503);
}
}
# file: docker/caddy/Caddyfile
{
admin off
# debug
on_demand_tls {
ask http://laravel.test/caddy
}
local_certs
}
:80 {
reverse_proxy laravel.test {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Port 443
# header_up X-Forwarded-Proto {scheme}
health_timeout 5s
}
}
:443 {
tls internal {
on_demand
}
reverse_proxy laravel.test {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Port 443
# header_up X-Forwarded-Proto {scheme}
health_timeout 5s
}
}
# file: docker-compose.yml
# ...
laravel.test:
# Comment or remove ports
# ports:
# - "${APP_PORT:-80}:80"
# ...
caddy:
build:
context: "./docker/caddy"
dockerfile: Dockerfile
args:
WWWGROUP: "${WWWGROUP}"
restart: unless-stopped
ports:
- "${APP_PORT:-80}:80"
- "${APP_SSL_PORT:-443}:443"
environment:
LARAVEL_SAIL: 1
HOST_DOMAIN: laravel.test
volumes:
- "./docker/caddy/Caddyfile:/etc/caddy/Caddyfile"
- ".:/srv:cache"
- "./docker/caddy/certificates:/data/caddy/certificates/local"
- "./docker/caddy/authorities:/data/caddy/pki/authorities/local"
- "sailcaddy:/data:cache"
- "sailcaddyconfig:/config:cache"
networks:
- sail
depends_on:
- laravel.test
# ...
# ...
volumes:
# ...
sailcaddy:
external: true
sailcaddyconfig:
driver: local
# file: docker/caddy/Dockerfile
FROM caddy:alpine
LABEL maintainer="Adrian Mejias"
ARG WWWGROUP
ENV DEBIAN_FRONTEND noninteractive
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apk add --no-cache bash \
&& apk add --no-cache nss-tools \
&& rm -rf /var/cache/apk/*
RUN addgroup -S $WWWGROUP
RUN adduser -G $WWWGROUP -u 1337 -S sail
COPY start-container /usr/local/bin/start-container
RUN chmod +x /usr/local/bin/start-container
ENTRYPOINT ["start-container"]
# file: docker/caddy/start-container
#!/usr/bin/env sh
if [ ! -z "$WWWUSER" ]; then
addgroup $WWWUSER sail
fi
if [ $# -gt 0 ]; then
# @todo find alpine equivilent of below
# exec gosu $WWWUSER "$@"
else
/usr/bin/caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
fi
# file: app/Http/Middleware/TrustProxies.php
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array|string|null
*/
protected $proxies = '*'; // Add wildcard or specific domain(s)
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}
# file: routes/web.php
<?php
use App\Http\Controllers\CaddyController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/caddy', CaddyController::class)->name('caddy');
// ...
@vik0803
Copy link

vik0803 commented Oct 26, 2021

@adrianmejias Thanks for sharing it.

I am new to Caddy and your example really helped me understanding the basic stuff on how Caddy can be used with Laravel.

Though I have a question.

What if we need to set up a SaaS based product with multi-tenant setup.

For e.g xyz.com is used to serve the website.
*.xyz.com is used for each tenant so tenant1.xyz.com, tenant2.xyz.com

As the above example is working fine without Caddy.

But now if I need to setup abc.client1.com -> tenant1.xyz.com with SSL how do I achieve that using Caddy.

I see lots of developers says that Caddy can be used in such cases and the same is used by OhDear as well but I couldnt find the best scenario that can help me in configuring Caddy file.

I would appreciate your help.

Thanks,
Vik.

@adrianmejias
Copy link
Author

@adrianmejias Thanks for sharing it.

I am new to Caddy and your example really helped me understanding the basic stuff on how Caddy can be used with Laravel.

Though I have a question.

What if we need to set up a SaaS based product with multi-tenant setup.

For e.g xyz.com is used to serve the website. *.xyz.com is used for each tenant so tenant1.xyz.com, tenant2.xyz.com

As the above example is working fine without Caddy.

But now if I need to setup abc.client1.com -> tenant1.xyz.com with SSL how do I achieve that using Caddy.

I see lots of developers says that Caddy can be used in such cases and the same is used by OhDear as well but I couldnt find the best scenario that can help me in configuring Caddy file.

I would appreciate your help.

Thanks, Vik.

Are you referring to this link? https://ohdear.app/blog/how-we-used-caddy-and-laravels-subdomain-routing-to-serve-our-status-pages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment