This Repository is a collection of stacks, that I've made for various reasons.
Methods for obtaining a Certificate, in thise case for local development, can be found here.
The purpose of this Stack
, was to learn more about the nginx server, the content of the configuration files, as well as how a full development configuration for php could look like.
While I have generated the config files, I've also learned more about what they do.
-
Nginx Server
- Configured for
HTTPS
withHTTP/2
. - Redirects all
HTTP
requests toHTTPS
. - Listening for the custom local
domain => your_domain.com
. - The
Container
path forNGINX
andPHP FPM
is/var/www/domain
. - The
NGINX
root directory for the files that should only be served is pointing to thePublic
directory (Case Sensitive).
- Configured for
-
PHP FPM
- A
php.ini-development
andphp.ini-production
template.- Both have the same values, as the original templates, except for
[extension_dir, pdo_mysql]
. php.ini-development
has XDebug enabled and configured.
- Both have the same values, as the original templates, except for
- A
php.ini
file. (Currently set for development). - PDO_MySQL installed and enabled.
- XDebug installed and enabled.
- A
-
PHPMyAdmin
- Used for easy database management.
HTTPS
only.
-
MariaDB
- Using the
create_tables.sql
from PHPMyAdmin, thePHPMyAdmin Database
is being populated.
- Using the
This Stack
is a demo for how to use the NGINXProxyManager, in order to obtain a wildcard Certificate, allowing for a trusted local environment. (Though this can also be used for external access).
Mainly using the NGINXProxyManager.
The other services can be found here.
Difference? The SSL directories are gone, which also means that they are not being copied or added. On top of that the Dockerfile and NGINX Server config no longer have SSL directives.
- Self Signed Certificates (SSC)
- Signed Wildcard Certificates using LetsEnCrypt, with a free option! (LEC)
Generating and using a SSC (Self Signed Certificate) can be a bit much, especially if the topic is one you don't know much about. There are plenty of resources out there, in the world wild web, but they don't necessarily have the full information needed to pull it of.
In order to be able to locally map an IP-Address to a "Domain", you need to edit the hosts file with elevated privileges.
cd c:\Windows\System32\Drivers\etc\
notepad hosts
This is how the hosts
file could look like, if you have docker installed:
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
# Added by Docker Desktop
192.168.178.157 host.docker.internal
192.168.178.157 gateway.docker.internal
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
You can just go to the end of the hosts
file and for example write the following:
# Custom Defined Mappings
127.0.0.1 your_domain.com
! Save and close the hosts file and powershell window, otherwise the changes might not take effect!
For this step, it is time to get a temporary container
that allows us to generate what we need.
There are many ways to do this and probably even better ones, but I'm sticking to something, where I can safely say that it works.
We will create an ubuntu container, update the package list, install openssl and generate our files.
cd LOCATION_WHERE_YOU_WANT_TO_STORE_YOUR_CERTS
docker run -it --rm -v ${pwd}:/home/certs -w /home/certs ubuntu
- docker run => Creates a
Container
from an image. - -it => Launches that
Container
in interactive mode. (Especially necessary if the container has no job to do). - --rm => Removes the
Container
after exiting or stopping it. - -v => Either creates a volume or binds / mounts a host path to a
container
path. (Bind in this case). - -w => Sets the work directory, which will be the path you start in.
- image:tag => The image you want to use for the
container
. (ubuntu:latest in this case).
If the openssl commands below do not work with this docker run command, try installing it.
apt update && apt install openssl
Due to some issues, that can arise when failing to fill out specific questions upon generating the CSR, I've decided to update this entry with an example config file.
Just replace everything in <> with the actual value and save it as openssl.cnf
, within the same directory you've launched your docker run
command in.
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = <Country Name (2 letter code)>
ST = <State or Province Name (full name)>
L = <Locality Name (eg, city)>
O = <Organization Name (eg, company)>
OU = <Organizational Unit Name (eg, section)>
CN = <Common Name (e.g., the domain name)>
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = <your-domain-name>
openssl req -new -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr -config openssl.cnf
- -req => Initiates the creation of a CSR (Certificate Signing Request).
- -new => Indicates that a new CSR is being created.
- -newkey rsa:2048 => Creates a new RSA private key of 2048 bits.
- -nodes => Prevents the encryption of the output key.
- -keyout domain.key => Specifies the filename to write the newly created private key to.
- -out domain.csr => Specifies the output filename to write the CSR to.
- -config => This specifies the configuration file to use, which includes the details for the SAN(s). (Subject Alternative Name(s)).
openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt -extensions v3_req -extfile openssl.cnf
- -x509 => Is the OpenSSL utility for displaying and manipulating X.509 certificates.
- -req => Indicates that a certificate signing request (CSR) is being used.
- -days 365 => Specifies that the certificate will be valid for 365 days.
- -in domain.csr => Specifies the input file, which is the CSR.
- -signkey domain.key => Specifies the file with the private key to use for signing.
- -out domain.crt => Specifies the output file, which is the certificate.
- -extensions v3_req => This specifies the extensions to use for the certificate, which are defined in the configuration file.
- -extfile => This specifies the configuration file that contains the extension details, including the SANs.
In order to trust the certificate, as well as remove the warnings and insecurity flags, you have to install it.
- Open the control panel.
- Search of
Manage User Certificates
. - Navigate to
Trusted Root Certification Authorities
. - RightClick
Certificates
. - Go to
All Tasks > Import
and follow the Instructions.
Now, that you have your files, you can use them .crt
and .key
to enable https for your web based projects.
Ever wanted a dynamic way, to give everything you serve a subdomain without requesting a certificate for every subdomain? Well, your in luck! The answer is (LEC) LetsEnCrypt. In this section I'm showing you a way (or two), to generate one certificate and use it for an x amount of services.
Granted, you will need to own a Domain, but don't be discouraged, because while there are TLD
you can try on sites like NameCheap, CloudFlare or DigitalOcean, you can also use a free service called DuckDNS, which will provide you a free subdomain you can branch of.
I was wondering if there is a way to get a certificate for an IP address, so that local development can continue in a free manner, but then I finally figured out, how to make a SSC (Self Signed Certificate) work under windows.
But then I learned that (LEC) Let'sEncrypt has more than just the HTTP challenge, which makes this entire thing possible. You can make a challenge, that verifies you as the Domain owner, allowing for a wildcard certificate.
Whether you own a Domain from DuckDNS, or working with a paid one, the only difference would be, that one a real one you would have to specify a CNAME
entry where the alias
would be *
and point tp @
or root
.
The IP of your A Type
entry points to whatever your use case is. If you only want to access whatever you develop on your local machine, then you can point it to 127.0.0.1
. If you want to be able to access your services on your LAN
, then you should use your local IP Address.
I went with buying a Domain from NameCheap and configuring it with the DNS from CloudFlare. But in the following steps, I'll use DuckDNS, because I want everyone, to be able to follow along.
There are other solutions out there, but this is for now, the simplest one.
! You don't have to / should bind any ports of a service, that runs or is connected to this Stack.
+ Only the ProxyManager needs to expose ports.
Persistent volume variant:
version: '3.8'
name: "web_stack_with_proxy"
services:
nginx_proxy_manager:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx_proxy_manager
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- proxy_manager_data:/data
- proxy_manager_letsencrypt:/etc/letsencrypt
volumes:
proxy_manager_data:
proxy_manager_letsencrypt:
Shared directories (Bind / Mount), for when you want to use either the Certificates
or Config Data
for example in another Container
or Stack
:
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
This is fairly simple. You'll need to log in, set your first user and then you are ready to do the certificate request.
DEFAULT_USER: admin@example.com
DEFAULT_PASSWORD: changeme
Navigate to the SSL Certificates
panel and then click on Add SSL Certificate
.
Now, enter your Domains, which could look like your_domain.tld
and *.your_domain.tld
. After that you must check the Use a DNS Challenge
.
Choose your DNS provider, fill out whatever is required, change the Propagation
time to 120s
, because the challenge can fail, if the time is too short, even though you did everything right and Agree the TOS
.
You can now download that certificate, if you need to.
Let's imagine you have an NGINX Service
and it only listens to port 80 and does not use SSL. Well seeing that we are using a Proxy
, we are no longer directly talking to that (other) NGINX
, so we can just do the following:
- Domain Names => Set's the mapping of what you type in the URL.
- Scheme => Whether your target is HTTP or HTTPS.
- Forward Hostname / IP => The IP of the HOST Client you want to reach. (Forward to).
You can also define a suitable subdomain, just like this:
Now, in order to secure this forwarding, we have to choose the Certificate
to use for the forwarding, as well as whether we want to force SSL
, enable HTTP/2
and more.