Compare commits
No commits in common. "main" and "f1faf3fedfb73784d5459902ac906ed59bbbcdd0" have entirely different histories.
main
...
f1faf3fedf
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -62,7 +62,6 @@
|
||||
*.min.css text eol=lf
|
||||
*.js text eol=lf
|
||||
*.min.js text eol=lf
|
||||
*.php text eol=lf
|
||||
|
||||
# Visual Studio projects (Rider also)
|
||||
*.cs diff=csharp
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="accountSettings">
|
||||
<option name="activeRegion" value="us-east-1" />
|
||||
<option name="recentlyUsedRegions">
|
||||
<list>
|
||||
<option value="us-east-1" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationConfigOverride">
|
||||
<CommitMessageValidationOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</CommitMessageValidationOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownSettings">
|
||||
<enabledExtensions>
|
||||
<entry key="MermaidLanguageExtension" value="false" />
|
||||
<entry key="PlantUMLLanguageExtension" value="false" />
|
||||
</enabledExtensions>
|
||||
</component>
|
||||
</project>
|
@ -2,19 +2,12 @@
|
||||
<project version="4">
|
||||
<component name="CommitMessageInspectionProfile">
|
||||
<profile version="1.0">
|
||||
<inspection_tool class="BodyLimit" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="BodyLimit" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectBodySeparation" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectLimit" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
<component name="GitSharedSettings">
|
||||
<option name="FORCE_PUSH_PROHIBITED_PATTERNS">
|
||||
<list>
|
||||
<option value="master main" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitCommitMessageStorage">
|
||||
<option name="messageStorage">
|
||||
<MessageStorage />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxBlameSettings">
|
||||
<option name="version" value="2" />
|
||||
</component>
|
||||
</project>
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="3" />
|
||||
</component>
|
||||
</project>
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CommitMessageInspectionProfile">
|
||||
<profile version="1.0">
|
||||
<inspection_tool class="BodyLimit" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectBodySeparation" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="RIGHT_MARGIN" value="50" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -1,30 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="build/Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="Docker (WSL)">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="docker.asifbacchus.dev/nginx/ab-nginx:5.2.1-1.27" />
|
||||
<option name="buildArgs">
|
||||
<list>
|
||||
<DockerEnvVarImpl>
|
||||
<option name="name" value="BUILD_DATE" />
|
||||
<option name="value" value="2024-08-31" />
|
||||
</DockerEnvVarImpl>
|
||||
<DockerEnvVarImpl>
|
||||
<option name="name" value="GIT_COMMIT" />
|
||||
<option name="value" value="9104126356" />
|
||||
</DockerEnvVarImpl>
|
||||
<DockerEnvVarImpl>
|
||||
<option name="name" value="INTERNAL_VERSION" />
|
||||
<option name="value" value="5.2.1" />
|
||||
</DockerEnvVarImpl>
|
||||
</list>
|
||||
</option>
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="containerName" value="" />
|
||||
<option name="sourceFilePath" value="build/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
3
.vscode/numbered-bookmarks.json
vendored
Normal file
3
.vscode/numbered-bookmarks.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"bookmarks": []
|
||||
}
|
51
LICENSE
51
LICENSE
@ -1,51 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Asif Bacchus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
NOTWITHSTANDING THE ABOVE, this Software contains software provided by NGINX
|
||||
and its contributors which is subject to the following BSD license:
|
||||
|
||||
Copyright (C) 2002-2021 Igor Sysoev
|
||||
Copyright (C) 2011-2021 Nginx, Inc.
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Any licensing or other inquires should be directed to Asif Bacchus via
|
||||
email at 'asif@asifbacchus.dev' or by filing issues on this Software's git
|
||||
repository at 'https://git.asifbacchus.dev/ab-docker/ab-nginx.git'.
|
128
README.md
128
README.md
@ -1,93 +1,63 @@
|
||||
# ab-nginx
|
||||
|
||||
Containerized fully-functional implementation of NGINX running on Alpine **as a fully NON-ROOT user**. The container by default is a 'blank slate' that just serves files out of the box. Changing configuration, server blocks and content is accomplished with bind-mounts using a sensible, simple directory structure. The container auto-detects mounted certificates and switches to TLS automatically. Available [Helper scripts](https://asifbacchus.dev/public/docker/nginx/ab-nginx/) make certificate mounting easier, allow for custom docker networks and more. The container by default can be used as a Let’s Encrypt endpoint with tools like certbot.
|
||||
|
||||
**Version 5.x adds the following features:**
|
||||
|
||||
- container auto-generates missing Diffie-Hellman Parameters (‘dhparams’) when using TLSv1.2
|
||||
- included a script within the container to generate self-signed certificates with a *group* readable private key so they can be shared between services in a stack by aligning container and host GIDs
|
||||
- helper scripts have been moved out of the ‘releases’ and hosted separately as straight-downloads so there is no need to clone the entire repo -- located at: [https://asifbacchus.dev/public/docker/nginx/ab-nginx/](https://asifbacchus.dev/public/docker/nginx/ab-nginx/)
|
||||
Containerized fully-functional implementation of NGINX running on Alpine **as a fully NON-ROOT user**. The container by default is a 'blank slate' that just serves files out of the box. Changing configuration, server blocks and content is accomplished with bind-mounts using a sensible, simple directory structure. The container auto-detects mounted certificates and switches to TLS automatically. [Helper scripts](https://git.asifbacchus.dev/ab-docker/ab-nginx/releases) in the git repo make certificate mounting easier, allow for custom docker networks and more. The container by default can be used as a Let’s Encrypt endpoint with tools like certbot.
|
||||
|
||||
## Contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Alternate repository](#alternate-repository)
|
||||
- [Signed containers](#signed-containers)
|
||||
- [Documentation and scripts](#documentation-and-scripts)
|
||||
- [Permissions](#permissions)
|
||||
* [Option 1: rebuild container with different UID/GID](#option-1-rebuild-container-with-different-uidgid)
|
||||
* [Option 2: specify UID/GID at runtime](#option-2-specify-uidgid-at-runtime)
|
||||
- [Container layout](#container-layout)
|
||||
* [Content directory](#content-directory)
|
||||
* [Configuration directory](#configuration-directory)
|
||||
- [Quick-start](#quick-start)
|
||||
* [Mounting content](#mounting-content)
|
||||
* [Mounting configurations](#mounting-configurations)
|
||||
* [Mounting server-blocks](#mounting-server-blocks)
|
||||
- [TLS](#tls)
|
||||
* [Generate a self-signed certificate](#generate-a-self-signed-certificate)
|
||||
- [Environment variables](#environment-variables)
|
||||
- [Shell mode](#shell-mode)
|
||||
* [Drop to shell before NGINX loads](#drop-to-shell-before-nginx-loads)
|
||||
* [Enter a running container](#enter-a-running-container)
|
||||
- [Logs](#logs)
|
||||
- [Final thoughts](#final-thoughts)
|
||||
|
||||
<!-- tocstop -->
|
||||
[Alternate repository](#alternate-repository)<br>
|
||||
[Documentation and scripts](#documentation-and-scripts)<br>
|
||||
[Permissions](#permissions)<br>
|
||||
[Container layout](#container-layout)<br>
|
||||
[Content directory](#content-directory)<br>
|
||||
[Configuration directory](#configuration-directory)<br>
|
||||
[Quick-start](#quick-start)<br>
|
||||
[Mounting content](#mounting-content)<br>
|
||||
[Mounting configurations](#mounting-configurations)<br>
|
||||
[Mounting server-blocks](#mounting-server-blocks)<br>
|
||||
[TLS](#tls)<br>
|
||||
[Environment variables](#environment-variables)<br>
|
||||
[Shell mode](#shell-mode)<br>
|
||||
[Drop to shell before NGINX loads](#drop-to-shell-before-nginx-loads)<br>
|
||||
[Enter a running container](#enter-a-running-container)<br>
|
||||
[Logs](#logs)<br>
|
||||
[Final thoughts](#final-thoughts)
|
||||
|
||||
## Alternate repository
|
||||
|
||||
Throughout this document, I reference my repository on DockerHub (`asifbacchus/ab-nginx:tag`). You may also feel free to pull directly from my private registry instead which is guaranteed to have the most up-to-date releases. Simply use `docker.asifbacchus.dev/nginx/ab-nginx:tag`.
|
||||
|
||||
## Signed containers
|
||||
|
||||
Starting with the 5.x releases, I am no longer using Docker Notary to sign images. Instead, I’m using [CodeNotary](https://codenotary.io). This has several advantages, most notably that it doesn’t matter whether you use DockerHub or my private repo they will both have the same verifiable signature. To verify the signature, you would have to use CodeNotary’s vcn tool -- visit their site for the most up-to-date instructions.
|
||||
Throughout this document, I reference my repository on DockerHub (`asifbacchus/ab-nginx:tag`). You may also feel free to pull directly from my private registry instead, especially if you need signed containers. Simply use `docker.asifbacchus.dev/nginx/ab-nginx:tag`. I usually sign major dot-version releases (1.18, 1.19, etc.) as well as the 'latest' image.
|
||||
|
||||
## Documentation and scripts
|
||||
|
||||
Check out the [repo wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki) for detailed examples and documentation about the container and the [helper scripts](https://asifbacchus.dev/public/docker/nginx/ab-nginx/).
|
||||
Check out the [repo wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki) for detailed examples and documentation about the container and the [helper scripts](https://git.asifbacchus.dev/ab-docker/ab-nginx/releases) which are located [here](https://git.asifbacchus.dev/ab-docker/ab-nginx/releases).
|
||||
|
||||
## Permissions
|
||||
|
||||
The container does **NOT** run under the root account. It runs under a user named *www-docker* with a UID and GID of 8080. **This means any files you mount into the container need to be readable (and/or writable depending on your use-case) by UID 8080 or GID 8080**. This does not just mean content files, it also includes configurations, server-blocks and *certificates*! Before mounting your files, ensure this is the case. There are more detailed instructions in the [wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki) if you need help setting file permissions.
|
||||
The container does **NOT** run under the root account. It runs under a user named *www-docker* with a UID of 8080. **This means any files you mount into the container need to be readable (and/or writable depending on your use-case) by UID 8080**. This does not mean just content files, it also includes configurations, server-blocks and *certificates*! Before mounting your files, ensure this is the case. There are more detailed instructions in the [wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki) if you need help setting file permissions.
|
||||
|
||||
This is a significant change versus most other NGINX implementations/containers where the main process is run as root and the *worker processes* run as a limited user. In those cases, permissions don’t matter since NGINX can always use the root account to read any files (and especially certificates!) it needs. Please understand this difference.
|
||||
This is a significant change versus most other NGINX implementations/containers where the main process is run as root
|
||||
and the *worker processes* run as a limited user. In those cases, permissions don’t matter since NGINX can always use
|
||||
the root account to read any files (and especially certificates!) it needs. Please understand this difference.
|
||||
|
||||
Most often you will end up wanting to change the container user’s GID so that you can assign it and related services appropriate permissions. To do this, you have two options:
|
||||
|
||||
### Option 1: rebuild container with different UID/GID
|
||||
|
||||
If you are integrating this container as part of a stack, then it might just make sense to “hard-code” the UID and/or GID to whatever works best for your environment. Fortunately, that’s pretty easy. Clone the [git repo](https://git.asifbacchus.dev/ab-docker/ab-nginx) and rebuild the container:
|
||||
If you need to change the UID, then you’ll need to rebuild the container using
|
||||
the [Dockerfile in the git repo](https://git.asifbacchus.dev/ab-docker/ab-nginx). The process would be something like
|
||||
this:
|
||||
|
||||
```bash
|
||||
# clone the repo
|
||||
cd /usr/local/src
|
||||
git clone https://git.asifbacchus.dev/ab-docker/ab-nginx
|
||||
|
||||
# change directory and build
|
||||
# change to the proper directory and build the container
|
||||
cd ab-nginx/build
|
||||
docker build --build-arg UID=xxxx --build-arg GID=yyyy --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') -t name:tag .
|
||||
docker build --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg UID=xxxx -t name:tag .
|
||||
```
|
||||
|
||||
- `UID=xxxx`: optional -- replace ‘xxxx’ with desired UID for www-docker user, in most cases the default is fine
|
||||
- `GID=yyyy`: replace ‘yyyy’ with desired GID for www-docker user --> this is probably what you want to change
|
||||
- `BUILD_DATE`: optional -- applies container build date in a standardized label
|
||||
- `name:tag`: you may, of course, name and tag your container anything you like
|
||||
|
||||
### Option 2: specify UID/GID at runtime
|
||||
|
||||
You may find it easier and more flexible to just specify the UID and/or GID at runtime. Again, you most likely want to set the GID so that it matches, say, your webdev user group and the container can then read and serve those files. Pretty easy, just add `--user "uid:gid"` to your docker run command. Here’s an example where the GID is changed to 6000:
|
||||
|
||||
```bash
|
||||
docker run -d ... --user "8080:6000" ... asifbacchus/ab-nginx:latest
|
||||
```
|
||||
Of course, replace *xxxx* with your desired UID for the *www-docker* user. Also, replace *name:tag* with whatever you want to tag your image.
|
||||
|
||||
## Container layout
|
||||
|
||||
### Content directory
|
||||
|
||||
All content is served from the NGINX default `/usr/share/nginx/html` directory within the container. The default set up serves everything found here and in all child directories. Bind-mount your content to the container’s webroot: `-v /my/webstuff:/usr/share/nginx/html`. **Remember that the container UID or GID must be able to read these files!**
|
||||
All content is served from the NGINX default `/usr/share/nginx/html` directory within the container. The default set up serves everything found here and in all child directories. To use your own content (this point of this whole thing, right? :wink:) bind-mount your content to the container’s webroot: `-v /my/webstuff:/usr/share/nginx/html`. **Remember that UID 8080 must be able to read these files!**
|
||||
|
||||
### Configuration directory
|
||||
|
||||
@ -112,11 +82,11 @@ ### Configuration directory
|
||||
├── ssl_certs.conf – (hard-coded for the container, best not to touch)
|
||||
```
|
||||
|
||||
Locations with \**starred descriptions** are designed to be overwritten via bind-mounts to customize the container. For more details on all of these files and what they do, please refer to the [repo wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki). **Remember that the container UID or GID needs to be able to read any files you choose to bind-mount over the container defaults!**
|
||||
Locations with \**starred descriptions** are designed to be overwritten via bind-mounts to customize the container. For more details on all of these files and what they do, please refer to the [repo wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki). **Remember that UID 8080 needs to be able to read any files you choose to bind-mount over the container defaults!**
|
||||
|
||||
## Quick-start
|
||||
|
||||
At its most basic, all you need to do is mount a directory with content to serve. For more advanced deployments, you can also mount various configurations. In most cases, you’ll also want to mount certificates so that SSL/TLS is an option. **Remember that the container’s UID/GID must be able to read everything you bind-mount!** Let’s run through some examples:
|
||||
At it’s most basic, all you need to do is mount a directory with content to serve. For more advanced deployments, you can also mount various configurations. In most cases, you’ll also want to mount certificates so that SSL/TLS is an option. **Remember that UID 8080 must be able to read everything you bind-mount!** Let’s run through some examples:
|
||||
|
||||
### Mounting content
|
||||
|
||||
@ -187,12 +157,12 @@ ## TLS
|
||||
| Full-chain certificate<br />(certificate concatenated with intermediates and root CA) | /certs/fullchain.pem |
|
||||
| Private key | /certs/privkey.pem |
|
||||
| Certificate chain<br />(intermediates concatenated with root CA) | /certs/chain.pem |
|
||||
| DH Parameters file<br />(Container will generate this file if not provided)<br />(NOT required for TLS 1.3-only mode) | /certs/dhparam.pem |
|
||||
| DH Parameters file<br />(NOT required for TLS 1.3-only mode) | /certs/dhparam.pem |
|
||||
|
||||
Once those files are available, you can run the container as follows:
|
||||
|
||||
```bash
|
||||
# TLS 1.2 (allows TLSv1.2 and TLSv1.3)
|
||||
# TLS 1.2 (requires: fullchain.pem, privkey.pem, chain.pem and dhparam.pem)
|
||||
docker run -d --name nginx --restart unless-stopped \
|
||||
-p 80:80 \
|
||||
-p 443:443 \
|
||||
@ -201,7 +171,7 @@ # TLS 1.2 (allows TLSv1.2 and TLSv1.3)
|
||||
-e SERVER_NAMES="domain.tld www.domain.tld" \
|
||||
asifbacchus/ab-nginx:latest
|
||||
|
||||
# TLS 1.3 only mode
|
||||
# TLS 1.3 only mode (requires fullchain.pem, privkey.pem and chain.pem)
|
||||
docker run -d --name nginx --restart unless-stopped \
|
||||
-p 80:80 \
|
||||
-p 443:443 \
|
||||
@ -214,25 +184,11 @@ # TLS 1.3 only mode
|
||||
|
||||
The container will load a secure configuration automatically, require SSL connections and redirect HTTP to HTTPS. If you want to enforce HSTS, simply set the HSTS environment variable to true by adding `-e HSTS=TRUE` before specifying the container name. Careful about doing this while testing though! Also, certificates should always be mounted read-only (`:ro`) for security reasons!
|
||||
|
||||
You may have noticed I also specified the `SERVER_NAMES` variable. This is necessary or SSL will not work since the hostname the server responds to must match the certificate being presented. **Make sure you set this environment variable to match your certificates!**
|
||||
|
||||
> N.B. If you are using your own server-blocks, then this environment variable is **NOT** required – it is only used by the container when auto-configuring the default server-blocks.
|
||||
You may have noticed I also specified the `SERVER_NAMES` variable. This is necessary or SSL will not work since the hostname the server responds to must match the certificate being presented. **Make sure you set this environment variable to match your certificates!** N.B. If you are using your own server-blocks, then this environment variable is **NOT** required – it is only used by the container when auto-configuring the default server-blocks.
|
||||
|
||||
If you want to integrate with Let's Encrypt, please refer to the [wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki).
|
||||
|
||||
Finally, I’d remind you once again that the container’s UID/GID must be able to read your certificate files! It is common practice to restrict the private key to root readability only (i.e. chown root:root & chmod 600/400) but, that would stop the NGINX user in the container from reading it and NGINX will exit with an error. I address ways to allow your certificate files to remain secure but still readable by the NGINX user in the [wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki). As a quick hint, it’s easiest to accomplish by changing the container GID!
|
||||
|
||||
### Generate a self-signed certificate
|
||||
|
||||
If you are testing a set-up or for whatever other reason want to use a self-signed certificate, the container can generate one for you. To make integration easier, the container does a trick with the *private key* by generating it with 6**4**0 permissions instead of 600 permissions. This means any member of the same group as the container can use this generated certificate-key pair. However, to make this work, you need to ensure the GID is set properly as mentioned in the [specify UID/GID at runtime](#option-2-specify-uidgid-at-runtime) section above. I’ll use GID=6000 in the following example.
|
||||
|
||||
To generate a certificate, invoke the container with the `generate-cert hostname` parameter. Let’s use server.example.com:
|
||||
|
||||
```bash
|
||||
docker run --rm -v /mycerts:/certs asifbacchus/ab-nginx generate-cert server.example.com
|
||||
```
|
||||
|
||||
In this example, your self-signed certificate (*fullchain.pem*), private key (*privkey.pem*) and certification chain/bundle (*chain.pem*) will be saved, group-readable, in your */mycerts/* directory on the host. Remember to import the certificate on any clients or you will get warnings!
|
||||
Finally, I’d remind you once again that UID 8080 must be able to read your certificate files! It is common practice to restrict the private key to root readability only (i.e. chown root:root & chmod 600/400) but, that would stop the NGINX user in the container from reading it and NGINX will exit with an error. I address ways to allow your certificate files to remain secure but still readable by the NGINX user in the [wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki).
|
||||
|
||||
## Environment variables
|
||||
|
||||
@ -254,14 +210,14 @@ ## Shell mode
|
||||
|
||||
### Drop to shell before NGINX loads
|
||||
|
||||
This is useful to verify where things mounted, etc. This is also useful if some configuration is causing NGINX to panic and shut down the container. Note that I’m using the `--rm` flag to auto-remove the container when I exit since there is no point in keeping a shell-mode instantiation around.
|
||||
This is useful to verify where things mounted, etc. This is also useful if some configuration is causing NGINX to panic and shutting down the container. Note that I’m using the `--rm` flag to auto-remove the container when I exit since there is no point in keeping a shell-mode instantiation around.
|
||||
|
||||
```bash
|
||||
docker run -it --rm \
|
||||
-v ~/web:/usr/share/nginx/html \
|
||||
-v ~/nginx/config:/etc/nginx/config \
|
||||
-v ~/nginx/servers:/etc/nginx/sites \
|
||||
-v ~/certs:/certs:ro \
|
||||
-v ~/certs:/certs \
|
||||
asifbacchus/ab-nginx /bin/sh
|
||||
```
|
||||
|
||||
@ -292,8 +248,8 @@ # show last 10 lines and follow from there in realtime (ctrl-c to stop)
|
||||
|
||||
## Final thoughts
|
||||
|
||||
I think that's everything to get you going if you are already familiar with docker and with NGINX in general. If you need more help, please [refer to the wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki). I've explained everything there in detail. Also, check out the [helper scripts](https://asifbacchus.dev/public/docker/nginx/ab-nginx/) especially if you are deploying certificates. The scripts take care of all the docker command-lines for you so you have much less typing!
|
||||
I think that's everything to get you going if you are already familiar with docker and with NGINX in general. If you need more help, please [refer to the wiki](https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki). I've explained everything there in detail. Also, check out the [helper scripts](https://git.asifbacchus.dev/ab-docker/ab-nginx/releases) especially if you are deploying certificates. The scripts take care of all the docker command-lines for you so you have much less typing!
|
||||
|
||||
If I've forgotten anything, you find any bugs or you have suggestions, please file an issue either on my private [git server](https://git.asifbacchus.dev/ab-docker/ab-nginx) or on [github](https://github.com/asifbacchus/ab-nginx). Also, I am *not* affiliated with NGINX in any way, so please **do not** bother them with any issues you find with this container. Bother me instead, I actually enjoy it!
|
||||
If I've forgotten anything, you find any bugs or you have suggestions, please file an issue either on my private [git server ](https://git.asifbacchus.dev/ab-docker/ab-nginx) or on [github](https://github.com/asifbacchus/ab-nginx). Also, I am *not* affiliated with NGINX in any way, so please **do not** bother them with any issues you find with this container. Bother me instead, I actually enjoy it!
|
||||
|
||||
**All the best and have fun!**
|
||||
|
@ -1,8 +1,8 @@
|
||||
#
|
||||
# build AB-NGINX container (based on NGINX mainline on Alpine linux)
|
||||
# build AB-NGINX container (based on NGINX mainline)
|
||||
#
|
||||
|
||||
ARG NGINX_VERSION=1.27
|
||||
ARG NGINX_VERSION=1.21.1
|
||||
FROM nginx:${NGINX_VERSION}-alpine
|
||||
ARG NGINX_VERSION
|
||||
|
||||
@ -21,14 +21,10 @@ RUN addgroup --gid ${GID} www-docker \
|
||||
--uid ${UID} \
|
||||
www-docker
|
||||
|
||||
# add libcap and allow nginx to bind to ports <1024;
|
||||
# extract fun error pages;
|
||||
# create /certs directory for auto-generation;
|
||||
# create LetsEncrypt challenge directory outside webroot
|
||||
# add libcap, allow nginx to bind to ports <1024, extract fun error pages & create LetsEncrypt challenge directory outside webroot
|
||||
RUN apk --update --no-cache add \
|
||||
libcap \
|
||||
openssl \
|
||||
&& apk --update --no-cache upgrade \
|
||||
&& setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx \
|
||||
&& cd /usr/share/nginx \
|
||||
&& rm -rf html/* \
|
||||
@ -38,7 +34,6 @@ RUN apk --update --no-cache add \
|
||||
&& rm -rf /tmp/* \
|
||||
&& rm -rf /docker-entrypoint.d \
|
||||
&& rm -f /docker-entrypoint.sh \
|
||||
&& mkdir /certs \
|
||||
&& mkdir /usr/share/nginx/letsencrypt
|
||||
|
||||
# health check
|
||||
@ -50,10 +45,9 @@ HEALTHCHECK \
|
||||
CMD curl --fail http://127.0.0.1:9000/nginx_status || exit 1
|
||||
|
||||
# standardized labels
|
||||
MAINTAINER Asif Bacchus <asif@asifbacchus.dev>
|
||||
LABEL maintainer="Asif Bacchus <asif@asifbacchus.dev>"
|
||||
LABEL dev.asifbacchus.docker.internalName="ab-nginx"
|
||||
LABEL org.opencontainers.image.author="Asif Bacchus <asif@asifbacchus.dev>"
|
||||
MAINTAINER Asif Bacchus <asif@bacchus.cloud>
|
||||
LABEL maintainer="Asif Bacchus <asif@bacchus.cloud>"
|
||||
LABEL org.opencontainers.image.author="Asif Bacchus <asif@bacchus.cloud>"
|
||||
LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/ab-nginx"
|
||||
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki"
|
||||
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/ab-nginx.git"
|
||||
@ -81,8 +75,6 @@ RUN chown -R www-docker:www-docker /usr/share/nginx \
|
||||
&& find /etc/nginx -type f -exec chmod 640 {} \; \
|
||||
&& chown www-docker:www-docker /var/cache/nginx \
|
||||
&& chown www-docker:www-docker /var/log/nginx \
|
||||
&& chown www-docker:www-docker /certs \
|
||||
&& chmod 700 /certs \
|
||||
&& chmod 644 /etc/selfsigned.cnf \
|
||||
&& chmod 755 /usr/local/bin/generate-cert /usr/local/bin/entrypoint.sh
|
||||
USER www-docker
|
||||
@ -110,7 +102,7 @@ ARG GIT_COMMIT
|
||||
ARG INTERNAL_VERSION
|
||||
LABEL org.opencontainers.image.revision=${GIT_COMMIT}
|
||||
LABEL org.opencontainers.image.version=${NGINX_VERSION}
|
||||
LABEL dev.asifbacchus.docker.internalVersion=${INTERNAL_VERSION}-${NGINX_VERSION}
|
||||
LABEL app.asifbacchus.docker.internalVersion=${INTERNAL_VERSION}-${NGINX_VERSION}
|
||||
LABEL org.opencontainers.image.created=${BUILD_DATE}
|
||||
|
||||
#EOF
|
||||
|
0
build/generate-cert.sh
Executable file → Normal file
0
build/generate-cert.sh
Executable file → Normal file
@ -1,29 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# generate checksums from provided path suitable for use by 'update.sh'
|
||||
#
|
||||
|
||||
# check for missing path to helper files, otherwise strip trailing slash
|
||||
if [ -z "$1" ]; then
|
||||
printf "\nPlease supply path to helper files. Exiting.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
srcDir="${1%/}"
|
||||
|
||||
# verify path exists and is accessible
|
||||
if ! [ -d "$srcDir" ]; then
|
||||
printf "\nUnable to find or read supplied path to helper files. Exiting.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# generate checksum file
|
||||
\rm -f "${srcDir}/checksums.sha256"
|
||||
find "${srcDir}/" -type f -exec sha256sum {} + >>./checksums.sha256
|
||||
sed -i "s+$srcDir/++g" ./checksums.sha256
|
||||
\mv ./checksums.sha256 "${srcDir}/"
|
||||
|
||||
# exit gracefully
|
||||
exit 0
|
||||
|
||||
#EOF
|
@ -6,23 +6,6 @@
|
||||
###
|
||||
|
||||
|
||||
#
|
||||
# Container options
|
||||
#
|
||||
|
||||
# Specify a particular tag to 'version pin' the ab-nginx container.
|
||||
TAG=latest
|
||||
|
||||
# Specify a runtime UID and GID for the container user. This is useful to
|
||||
# ensure the container can read and/or write to locations on the host or
|
||||
# has access to files shared between members of a container stack.
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: NGINX_UID=8080, NGINX_GID=8080
|
||||
# VALID OPTIONS: any permissible and available UID/GID value
|
||||
NGINX_UID=8080
|
||||
NGINX_GID=8080
|
||||
|
||||
|
||||
#
|
||||
# Network options
|
||||
#
|
||||
@ -33,7 +16,7 @@ NGINX_GID=8080
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: nginx_network
|
||||
# VALID OPTIONS: network names acceptable to the docker engine
|
||||
NETWORK=nginx_network
|
||||
#NETWORK=nginx_network
|
||||
|
||||
# If you want to specify a particular IP subnet for the network to be created
|
||||
# as per the above variable, specify it here. Again, if you don't know what
|
||||
@ -41,7 +24,7 @@ NETWORK=nginx_network
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: '172.31.254.0/24'
|
||||
# VALID OPTIONS: subnet in CIDR format
|
||||
SUBNET='172.31.254.0/24'
|
||||
#SUBNET='172.31.254.0/24'
|
||||
|
||||
|
||||
#
|
||||
@ -55,7 +38,7 @@ SUBNET='172.31.254.0/24'
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: Etc/UTC
|
||||
# VALID OPTIONS: IANA time zones in TZ format
|
||||
TZ=Etc/UTC
|
||||
#TZ=Etc/UTC
|
||||
|
||||
|
||||
#
|
||||
@ -72,8 +55,7 @@ TZ=Etc/UTC
|
||||
#
|
||||
# REQUIRED: YES, if using SSL and default server-blocks
|
||||
# DEFAULT: "_"
|
||||
# EXAMPLE: HOSTNAMES="domain.tld www.domain.tld server.domain.tld alt.domain.tld"
|
||||
HOSTNAMES="_"
|
||||
#HOSTNAMES="domain.tld www.domain.tld server.domain.tld alt.domain.tld"
|
||||
|
||||
# Ports to listen on:
|
||||
# If you need to use ports other than HTTP=80 and HTTPS=443, remember to set up
|
||||
@ -83,8 +65,8 @@ HOSTNAMES="_"
|
||||
# you use here.
|
||||
# REQUIRED: NO
|
||||
# DEFAULTS: 80 and 443, respectively
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
#HTTP_PORT=80
|
||||
#HTTPS_PORT=443
|
||||
|
||||
# Access logging (global preference):
|
||||
# Unless overridden in a server/location block, access logging will be handled
|
||||
@ -92,7 +74,7 @@ HTTPS_PORT=443
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: OFF
|
||||
# VALID OPTIONS: 'ON' or 'OFF'
|
||||
ACCESS_LOG=OFF
|
||||
#ACCESS_LOG=OFF
|
||||
|
||||
|
||||
#
|
||||
@ -107,7 +89,7 @@ ACCESS_LOG=OFF
|
||||
# Only files with a ".conf" extension will be loaded! If you want to disable a
|
||||
# file, simply change its extension (i.e. '.conf.disabled').
|
||||
#
|
||||
# REMEMBER: Your configuration files must be readable by the container UID/GID!
|
||||
# REMEMBER: Your configuration files must be readable by UID 8080!
|
||||
CONFIG_DIR=$(pwd)/config
|
||||
|
||||
# Specify a directory containing your NGINX server-block configurations (if any)
|
||||
@ -121,7 +103,7 @@ CONFIG_DIR=$(pwd)/config
|
||||
# Only files with a ".conf" extension will be loaded! If you want to disable a
|
||||
# file, simply change its extension (i.e. '.conf.disabled').
|
||||
#
|
||||
# REMEMBER: Your server-block files must be readable by the container UID/GID!
|
||||
# REMEMBER: Your server-block files must be readable by UID 8080!
|
||||
SERVERS_DIR=$(pwd)/sites
|
||||
|
||||
# Specify a directory containing 'snippets' of NGINX code you want/need to
|
||||
@ -132,11 +114,11 @@ SERVERS_DIR=$(pwd)/sites
|
||||
# instead of having to type the same thing many times.
|
||||
|
||||
# This is totally optional! Comment this variable to disable it.
|
||||
# REMEMBER: Your snippets must be readable by the container UID/GID!
|
||||
# REMEMBER: Your snippets must be readable by UID 8080!
|
||||
SNIPPETS_DIR=$(pwd)/snippets
|
||||
|
||||
# Specify a directory with the content you want to serve.
|
||||
# REMEMBER: This directory must be readable by the container UID/GID!
|
||||
# REMEMBER: This directory must be readable by UID 8080!
|
||||
WEBROOT_DIR=/var/www
|
||||
|
||||
|
||||
@ -149,27 +131,26 @@ WEBROOT_DIR=/var/www
|
||||
# REQUIRED: NO
|
||||
# DEFAULT: FALSE
|
||||
# VALID OPTIONS: 'TRUE', 'FALSE'
|
||||
HSTS=FALSE
|
||||
#HSTS=FALSE
|
||||
|
||||
# TLS 1.3 mode:
|
||||
# If 'FALSE' (default), NGINX will accept both TLS 1.2 and 1.3 connections.
|
||||
# If 'TRUE', only TLS 1.3 connections will be accepted.
|
||||
TLS13_ONLY=FALSE
|
||||
#TLS13_ONLY=FALSE
|
||||
|
||||
|
||||
#
|
||||
# Certificate files
|
||||
#
|
||||
# If you are mounting symlinks you MUST specify the full path of the symlink so
|
||||
# the target is resolved!
|
||||
# the target is resolved! DH (Diffie-Hellman Parameters file) is only required
|
||||
# if using TLS 1.2.
|
||||
#
|
||||
# REMEMBER: ALL files must be readable by container UID/GID!
|
||||
# EXAMPLES:
|
||||
# SSL_CERT=/path/to/your/ssl-certificate/fullchain.pem
|
||||
# SSL_KEY=/path/to/your/ssl-private-key/privkey.pem
|
||||
# SSL_CHAIN=/path/to/your/ssl-certificate-chain/chain.pem
|
||||
SSL_CERT=""
|
||||
SSL_KEY=""
|
||||
SSL_CHAIN=""
|
||||
# REMEMBER: ALL files must be readble by UID 8080!
|
||||
#SSL_CERT=/path/to/your/ssl-certificate/fullchain.pem
|
||||
#SSL_KEY=/path/to/your/ssl-private-key/privkey.pem
|
||||
#SSL_CHAIN=/path/to/your/ssl-certificate-chain/chain.pem
|
||||
#DH=/path/to/your/diffie-hellman-parameters-file/dhparam.pem
|
||||
|
||||
|
||||
#EOF
|
500
helpers/ab-nginx.sh
Executable file → Normal file
500
helpers/ab-nginx.sh
Executable file → Normal file
@ -4,239 +4,120 @@
|
||||
# start ab-nginx container using params file variables
|
||||
#
|
||||
|
||||
#
|
||||
# text formatting presets
|
||||
if command -v tput >/dev/null; then
|
||||
cyan=$(tput bold)$(tput setaf 6)
|
||||
err=$(tput bold)$(tput setaf 1)
|
||||
magenta=$(tput sgr0)$(tput setaf 5)
|
||||
norm=$(tput sgr0)
|
||||
yellow=$(tput sgr0)$(tput setaf 3)
|
||||
width=$(tput cols)
|
||||
cyan=$(tput bold)$(tput setaf 6)
|
||||
err=$(tput bold)$(tput setaf 1)
|
||||
magenta=$(tput sgr0)$(tput setaf 5)
|
||||
norm=$(tput sgr0)
|
||||
yellow=$(tput sgr0)$(tput setaf 3)
|
||||
width=$(tput cols)
|
||||
else
|
||||
cyan=''
|
||||
err=''
|
||||
magenta=''
|
||||
norm=''
|
||||
yellow=''
|
||||
width=80
|
||||
cyan=''
|
||||
err=''
|
||||
magenta=''
|
||||
norm=''
|
||||
yellow=''
|
||||
width=80
|
||||
fi
|
||||
|
||||
#
|
||||
# parameter defaults
|
||||
doShell=false
|
||||
doStatus=false
|
||||
doStop=false
|
||||
removeStopped=false
|
||||
### parameter defaults
|
||||
shell=false
|
||||
container_name="ab-nginx"
|
||||
NETWORK='nginx_network'
|
||||
SUBNET='172.31.254.0/24'
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
CONFIG_DIR=""
|
||||
SERVERS_DIR=""
|
||||
WEBROOT_DIR=""
|
||||
volumeMounts=""
|
||||
stopErr=0
|
||||
removeErr=0
|
||||
unset CONFIG_DIR
|
||||
unset SERVERS_DIR
|
||||
unset WEBROOT_DIR
|
||||
unset vmount
|
||||
|
||||
### functions
|
||||
|
||||
#
|
||||
# functions
|
||||
checkExist() {
|
||||
if [ "$1" = 'file' ]; then
|
||||
if [ ! -f "$2" ]; then
|
||||
printf "%s\nCannot find file: '$2'. Exiting.\n%s" "$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$1" = 'dir' ]; then
|
||||
if [ ! -d "$2" ]; then
|
||||
printf "%s\nCannot find directory: '$2'. Exiting.\n$%s" "$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$1" = 'file' ]; then
|
||||
if [ ! -f "$2" ]; then
|
||||
printf "%s\nCannot find file: '$2'. Exiting.\n%s" "$err" "$norm"
|
||||
exit 3
|
||||
fi
|
||||
return 0
|
||||
elif [ "$1" = 'dir' ]; then
|
||||
if [ ! -d "$2" ]; then
|
||||
printf "%s\nCannot find directory: '$2'. Exiting.\n$%s" "$err" "$norm"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
scriptHelp() {
|
||||
# header and description
|
||||
printf "\n%s" "$magenta"
|
||||
printf '%.0s-' $(seq "$width")
|
||||
printf "\n%s" "$norm"
|
||||
textBlock "This is a simple helper script so you can avoid typing lengthy commands when working with the ab-nginx container."
|
||||
textBlock "The script reads the contents of 'ab-nginx.params' and constructs various 'docker run' commands based on that file. The biggest time-saver is working with certificates. If they are specified in the params file, the script will automatically bind-mount them so nginx serves content via SSL by default."
|
||||
newline
|
||||
|
||||
# explanatory text
|
||||
textBlock "If you run the script with no parameters, it will execute the container 'normally': Run in detached mode with nginx automatically launched. If you specified certificates, nginx will serve over SSL by default."
|
||||
textBlock "Note: Containers (except shell) are always set to restart 'unless-stopped'. You must remove them manually if desired."
|
||||
printf "%s" "$magenta"
|
||||
newline
|
||||
|
||||
# parameters
|
||||
textBlock "The script has the following (optional) parameters:"
|
||||
textBlockParam 'parameter in cyan' 'default in yellow'
|
||||
newline
|
||||
textBlockParam '-n|--name' 'ab-nginx'
|
||||
textBlock "Set the name of the container, otherwise the default will be used."
|
||||
newline
|
||||
textBlockParam '-s|--shell' 'off: run in detached mode'
|
||||
textBlock "Enter the container using an interactive ASH/BusyBox shell. This happens after startup operations but *before* nginx is actually started. This is a great way to see configuration changes possibly stopping nginx from starting normally."
|
||||
newline
|
||||
textBlockParam '--status'
|
||||
textBlock "Run a search for all AB-NGINX containers and display their name and status."
|
||||
newline
|
||||
textBlockParam '--stop'
|
||||
textBlock "Stops the container specified by the '--name' parameter or with the default name 'ab-nginx'."
|
||||
newline
|
||||
textBlockParam '--remove | --stop-remove'
|
||||
textBlock "Stops and removes the container specified by the '--name' parameter or with the default name 'ab-nginx'."
|
||||
|
||||
# footer
|
||||
newline
|
||||
printf "%s" "$yellow"
|
||||
textBlock "More information can be found at: https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki"
|
||||
printf "\n%s" "$magenta"
|
||||
printf '%.0s-' $(seq "$width")
|
||||
printf "\n%s" "$norm"
|
||||
exit 0
|
||||
printf "\n%s%1000s\n" "$magenta" | tr " " "-" | cut -c -$width
|
||||
printf "%s" "$norm"
|
||||
textblock "This is a simple helper script so you can avoid typing lengthy commands when working with the ab-nginx container."
|
||||
textblock "The script reads the contents of 'ab-nginx.params' and constructs various 'docker run' commands based on that file. The biggest time-saver is working with certificates. If they are specified in the params file, the script will automatically bind-mount them so nginx serves content via SSL by default."
|
||||
newline
|
||||
textblock "If you run the script with no parameters, it will execute the container 'normally': Run in detached mode with nginx automatically launched. If you specified certificates, nginx will serve over SSL by default."
|
||||
textblock "Note: Containers (except shell) are always set to restart 'unless-stopped'. You must remove them manually if desired."
|
||||
printf "%s" "$magenta"
|
||||
newline
|
||||
textblock "The script has the following (optional) parameters:"
|
||||
textblockParam 'parameter in cyan' 'default in yellow'
|
||||
newline
|
||||
textblockParam '-n|--name' 'ab-nginx'
|
||||
textblock "Change the name of the container. This is cosmetic and does not affect operation in any way."
|
||||
newline
|
||||
textblockParam '-s|--shell' 'off: run in detached mode'
|
||||
textblock "Enter the container using an interactive POSIX shell. This happens after startup operations but *before* nginx is actually started. This is a great way to see configuration changes possibly stopping nginx from starting normally."
|
||||
printf "%s" "$yellow"
|
||||
newline
|
||||
textblock "More information can be found at: https://git.asifbacchus.app/ab-docker/ab-nginx/wiki"
|
||||
printf "%s%1000s\n" "$magenta" | tr " " "-" | cut -c -$width
|
||||
exit 0
|
||||
}
|
||||
|
||||
newline() {
|
||||
printf "\n"
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
textBlock() {
|
||||
printf "%s\n" "$1" | fold -w "$width" -s
|
||||
textblock() {
|
||||
printf "%s\n" "$1" | fold -w "$width" -s
|
||||
}
|
||||
|
||||
textBlockParam() {
|
||||
if [ -z "$2" ]; then
|
||||
# no default
|
||||
printf "%s%s%s\n" "$cyan" "$1" "$norm"
|
||||
else
|
||||
# default param provided
|
||||
printf "%s%s %s(%s)%s\n" "$cyan" "$1" "$yellow" "$2" "$norm"
|
||||
fi
|
||||
textblockParam() {
|
||||
if [ -z "$2" ]; then
|
||||
# no default
|
||||
printf "%s%s%s\n" "$cyan" "$1" "$norm"
|
||||
else
|
||||
# default param provided
|
||||
printf "%s%s %s(%s)%s\n" "$cyan" "$1" "$yellow" "$2" "$norm"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# pre-requisite checks
|
||||
### pre-requisite checks
|
||||
|
||||
# is docker installed?
|
||||
if ! command -v docker >/dev/null; then
|
||||
printf "%s\nCannot find docker... is it installed?\n%s" "$err" "$norm"
|
||||
exit 2
|
||||
if ! command -v docker > /dev/null; then
|
||||
printf "%s\nCannot find docker... is it installed?\n%s" "$err" "$norm"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# is user root or in the docker group?
|
||||
if [ ! "$(id -u)" -eq 0 ]; then
|
||||
if ! id -Gn | grep docker >/dev/null; then
|
||||
printf "%s\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n$%s" "$err" "$norm"
|
||||
exit 3
|
||||
fi
|
||||
if ! id -Gn | grep docker >/dev/null; then
|
||||
printf "%s\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n$%s" "$err" "$norm"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# process startup parameters
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h | -\? | --help)
|
||||
# display help
|
||||
scriptHelp
|
||||
exit 0
|
||||
;;
|
||||
-s | --shell)
|
||||
# start shell instead of default CMD
|
||||
doShell=true
|
||||
;;
|
||||
-n | --name)
|
||||
# container name
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nNo container name specified. Exiting.\n%s" "$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
container_name="$2"
|
||||
shift
|
||||
;;
|
||||
--status)
|
||||
# find containers and check their status
|
||||
doStatus=true
|
||||
;;
|
||||
--stop)
|
||||
# stop named container
|
||||
doStop=true
|
||||
;;
|
||||
--remove | --stop-remove)
|
||||
# stop and remove named container
|
||||
doStop=true
|
||||
removeStopped=true
|
||||
;;
|
||||
*)
|
||||
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
||||
printf "Use '--help' for valid options.\n\n%s" "$norm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
#
|
||||
# status check
|
||||
if [ "$doStatus" = "true" ]; then
|
||||
printf "\nFound the following AB-NGINX containers:\n"
|
||||
docker ps -a --filter "label=dev.asifbacchus.docker.internalName=ab-nginx"
|
||||
printf "\n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# stop container
|
||||
if [ "$doStop" = "true" ]; then
|
||||
printf "\nStopping container '%s'... " "$container_name"
|
||||
|
||||
# ensure container exists
|
||||
if ! docker inspect "$container_name" >/dev/null 2>&1; then
|
||||
printf "[ERROR]: No container with that name found.\n\n"
|
||||
exit 11
|
||||
fi
|
||||
|
||||
# stop and/or remove container
|
||||
if ! docker stop "$container_name" >/dev/null 2>&1; then stopErr=1; fi
|
||||
if [ "$removeStopped" = "true" ] && [ "$stopErr" -eq 0 ]; then
|
||||
if ! docker rm "$container_name" >/dev/null 2>&1; then removeErr=1; fi
|
||||
fi
|
||||
|
||||
# update status message
|
||||
if [ "$stopErr" -eq 1 ]; then
|
||||
printf "[ERROR]: Unable to stop container. Please try removing it manually.\n\n"
|
||||
exit 12
|
||||
fi
|
||||
if [ "$removeErr" -eq 1 ]; then
|
||||
printf "[STOPPED]\n"
|
||||
printf "[ERROR]: Unable to remove container. Please try removing it manually.\n\n"
|
||||
exit 13
|
||||
fi
|
||||
if [ "$removeStopped" = "true" ]; then
|
||||
printf "[REMOVED]\n\n"
|
||||
else
|
||||
printf "[STOPPED]\n\n"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# run container
|
||||
|
||||
# does the params file exist?
|
||||
checkExist 'file' './ab-nginx.params'
|
||||
|
||||
# read .params file
|
||||
# shellcheck source=ab-nginx.params.template
|
||||
. "./ab-nginx.params"
|
||||
|
||||
# fix case of TLS13_ONLY var
|
||||
if [ "$TLS13_ONLY" ]; then
|
||||
TLS13_ONLY=$(printf "%s" "$TLS13_ONLY" | tr "[:lower:]" "[:upper:]")
|
||||
TLS13_ONLY=$(printf "%s" "$TLS13_ONLY" | tr "[:lower:]" "[:upper:]")
|
||||
fi
|
||||
|
||||
# check for certs if using SSL
|
||||
@ -244,132 +125,175 @@ if [ "$SSL_CERT" ]; then checkExist 'file' "$SSL_CERT"; fi
|
||||
if [ "$SSL_KEY" ]; then checkExist 'file' "$SSL_KEY"; fi
|
||||
if [ "$SSL_CHAIN" ]; then checkExist 'file' "$SSL_CHAIN"; fi
|
||||
|
||||
# check for DHparam if using TLS1.2
|
||||
if [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'FALSE' ]; then
|
||||
if [ -z "$DH" ]; then
|
||||
printf "%s\nA DHparam file must be specified when using TLS 1.2. Exiting.%s\n" "$err" "$norm"
|
||||
exit 5
|
||||
else
|
||||
checkExist 'file' "$DH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# check if specified config directory exists
|
||||
if [ "$CONFIG_DIR" ]; then
|
||||
checkExist 'dir' "$CONFIG_DIR"
|
||||
checkExist 'dir' "$CONFIG_DIR"
|
||||
fi
|
||||
|
||||
# check if specified server-block directory exists
|
||||
if [ "$SERVERS_DIR" ]; then
|
||||
checkExist 'dir' "$SERVERS_DIR"
|
||||
checkExist 'dir' "$SERVERS_DIR"
|
||||
fi
|
||||
|
||||
# check if specified webroot directory exists
|
||||
if [ "$WEBROOT_DIR" ]; then
|
||||
checkExist 'dir' "$WEBROOT_DIR"
|
||||
checkExist 'dir' "$WEBROOT_DIR"
|
||||
fi
|
||||
|
||||
# set up volume mounts
|
||||
if [ "$CONFIG_DIR" ]; then
|
||||
volumeMounts="${volumeMounts} -v $CONFIG_DIR:/etc/nginx/config"
|
||||
vmount="$vmount -v $CONFIG_DIR:/etc/nginx/config"
|
||||
fi
|
||||
if [ "$SERVERS_DIR" ]; then
|
||||
volumeMounts="${volumeMounts} -v $SERVERS_DIR:/etc/nginx/sites"
|
||||
vmount="$vmount -v $SERVERS_DIR:/etc/nginx/sites"
|
||||
fi
|
||||
if [ "$SNIPPETS_DIR" ]; then
|
||||
volumeMounts="${volumeMounts} -v $SNIPPETS_DIR:/etc/nginx/snippets"
|
||||
vmount="$vmount -v $SNIPPETS_DIR:/etc/nginx/snippets"
|
||||
fi
|
||||
if [ "$WEBROOT_DIR" ]; then
|
||||
volumeMounts="${volumeMounts} -v $WEBROOT_DIR:/usr/share/nginx/html"
|
||||
vmount="$vmount -v $WEBROOT_DIR:/usr/share/nginx/html"
|
||||
fi
|
||||
# trim leading whitespace
|
||||
volumeMounts=${volumeMounts##[[:space:]]}
|
||||
vmount=${vmount##[[:space:]]}
|
||||
|
||||
# handle null HOSTNAMES
|
||||
if [ -z "$HOSTNAMES" ]; then HOSTNAMES="_"; fi
|
||||
|
||||
# process startup parameters
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h | -\? | --help)
|
||||
# display help
|
||||
scriptHelp
|
||||
exit 0
|
||||
;;
|
||||
-s | --shell)
|
||||
# start shell instead of default CMD
|
||||
shell=true
|
||||
;;
|
||||
-n | --name)
|
||||
# container name
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nNo container name specified. Exiting.\n%s" "$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
container_name="$2"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
||||
printf "Use '--help' for valid options.\n\n%s" "$norm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# create network if it doesn't already exist
|
||||
docker network inspect ${NETWORK} >/dev/null 2>&1 ||
|
||||
docker network create \
|
||||
--attachable \
|
||||
--driver=bridge \
|
||||
--subnet=${SUBNET} \
|
||||
${NETWORK}
|
||||
docker network create \
|
||||
--attachable \
|
||||
--driver=bridge \
|
||||
--subnet=${SUBNET} \
|
||||
${NETWORK}
|
||||
|
||||
# run without TLS
|
||||
if [ -z "$SSL_CERT" ]; then
|
||||
if [ "$doShell" = 'true' ]; then
|
||||
# exec shell
|
||||
printf "%s\nRunning SHELL on %s...%s\n" "$cyan" "$container_name" "$norm"
|
||||
# shellcheck disable=SC2086
|
||||
docker run --rm -it --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
${volumeMounts} \
|
||||
--network=${NETWORK} \
|
||||
-p ${HTTP_PORT}:80 \
|
||||
docker.asifbacchus.dev/nginx/ab-nginx:latest /bin/sh
|
||||
else
|
||||
# exec normally
|
||||
printf "%s\nRunning NGINX on %s...%s\n" "$cyan" "$container_name" "$norm"
|
||||
# shellcheck disable=SC2086
|
||||
docker run -d --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
${volumeMounts} \
|
||||
--network=${NETWORK} \
|
||||
-p ${HTTP_PORT}:80 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.dev/nginx/ab-nginx:${TAG:-latest}
|
||||
fi
|
||||
# run with TLS
|
||||
else
|
||||
if [ "$doShell" = 'true' ]; then
|
||||
if [ "$TLS13_ONLY" = 'FALSE' ]; then
|
||||
printf "%s\nRunning SHELL on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
else
|
||||
printf "%s\nRunning SHELL on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
docker run --rm -it --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
${volumeMounts} \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
docker.asifbacchus.dev/nginx/ab-nginx:${TAG:-latest} /bin/sh
|
||||
else
|
||||
if [ "$TLS13_ONLY" = 'FALSE' ]; then
|
||||
printf "%s\nRunning NGINX on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
else
|
||||
printf "%s\nRunning NGINX on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
docker run -d --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
${volumeMounts} \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.dev/nginx/ab-nginx:${TAG:-latest}
|
||||
fi
|
||||
if [ $shell = 'true' ]; then
|
||||
# exec shell
|
||||
printf "%s\nRunning SHELL on %s...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run --rm -it --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-p ${HTTP_PORT}:80 \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
|
||||
else
|
||||
# exec normally
|
||||
printf "%s\nRunning NGINX on %s...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run -d --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-p ${HTTP_PORT}:80 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest
|
||||
fi
|
||||
# run with TLS1.2
|
||||
elif [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'FALSE' ]; then
|
||||
if [ $shell = 'true' ]; then
|
||||
# exec shell
|
||||
printf "%s\nRunning SHELL on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run --rm -it --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-v "$DH":/certs/dhparam.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
|
||||
else
|
||||
# exec normally
|
||||
printf "%s\nRunning NGINX on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run -d --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-v "$DH":/certs/dhparam.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest
|
||||
fi
|
||||
# run with TLS1.3
|
||||
elif [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'TRUE' ]; then
|
||||
if [ $shell = 'true' ]; then
|
||||
# exec shell
|
||||
printf "%s\nRunning SHELL on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run --rm -it --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
|
||||
else
|
||||
# exec normally
|
||||
printf "%s\nRunning NGINX on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
|
||||
docker run -d --name "${container_name}" \
|
||||
--env-file ab-nginx.params \
|
||||
-e SERVER_NAMES="$HOSTNAMES" \
|
||||
$vmount \
|
||||
--network=${NETWORK} \
|
||||
-v "$SSL_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$SSL_KEY":/certs/privkey.pem:ro \
|
||||
-v "$SSL_CHAIN":/certs/chain.pem:ro \
|
||||
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/nginx/ab-nginx:latest
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# exit with code from docker
|
||||
exit "$?"
|
||||
|
||||
#
|
||||
# exit return codes
|
||||
# 0: normal exit, no errors
|
||||
# 1: missing or invalid parameter
|
||||
# 2: cannot find docker
|
||||
# 3: incorrect permissions to access docker
|
||||
# 1x: operation errors
|
||||
# 11 no container found with specified name
|
||||
# 12 unable to stop container
|
||||
# 13 unable to remove container
|
||||
# other refer to docker exit codes
|
||||
|
||||
#EOF
|
||||
### exit gracefully
|
||||
exit 0
|
@ -1,2 +0,0 @@
|
||||
resolver
|
||||
127.0.0.11;
|
@ -1,8 +1,8 @@
|
||||
- Place all your server block configuration files in this directory
|
||||
- This path should be bind-mounted to the container at:
|
||||
'/etc/nginx/sites'
|
||||
- this bind-mount will override the default server configurations
|
||||
included in the container by default.
|
||||
- this bind-mount will override the test pages included in the container by
|
||||
default.
|
||||
- All files should begin in the 'server' configuration context
|
||||
- ONLY files that end with '.conf' will be processed!
|
||||
- if you want to keep a file for reference or disable it temporarily,
|
||||
|
392
helpers/update.sh
Executable file → Normal file
392
helpers/update.sh
Executable file → Normal file
@ -1,96 +1,83 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# update script for ab-nginx container and utility scripts
|
||||
# version 2.1.0
|
||||
# script by Asif Bacchus
|
||||
#
|
||||
### update script for ab-nginx container and utility scripts
|
||||
# version 2.0.0
|
||||
# script by Asif Bacchus
|
||||
###
|
||||
|
||||
#
|
||||
# functions
|
||||
### functions
|
||||
errMsg() {
|
||||
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
|
||||
[ -n "$2" ] && exit "$2" || exit 1
|
||||
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
|
||||
exit 1
|
||||
}
|
||||
|
||||
errNotify() {
|
||||
printf "%s[ERROR]%s\n" "$err" "$norm"
|
||||
printf "%s[ERROR]%s\n" "$err" "$norm"
|
||||
}
|
||||
|
||||
okMsg() {
|
||||
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
|
||||
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
|
||||
}
|
||||
|
||||
okNotify() {
|
||||
printf "%s[OK]%s\n" "$ok" "$norm"
|
||||
}
|
||||
|
||||
makeDirectory() {
|
||||
if ! [ -d "./$1" ]; then
|
||||
if ! mkdir "./$1" >/dev/null 2>&1; then
|
||||
errMsgString="Unable to make '$1' directory."
|
||||
errMsg "$errMsgString" 40
|
||||
fi
|
||||
fi
|
||||
printf "%s[OK]%s\n" "$ok" "$norm"
|
||||
}
|
||||
|
||||
scriptHelp() {
|
||||
textNewline
|
||||
textBlock "Update ${containerName} container and helper script files"
|
||||
textBlock "${bold}Usage: ${localScriptName} [parameters]${norm}"
|
||||
textNewline
|
||||
textBlock "If run with no parameters, the script will update both the container and the helper script files, including this update script."
|
||||
textBlockHeader " parameters "
|
||||
textBlockParam "-h | -? | --help" "Display this help screen."
|
||||
textBlockParam "-c | --container | --container-only" "Update the docker container only."
|
||||
textBlockParam "-s| --scripts |--scripts-only" "Update the helper scripts (including this update script) only."
|
||||
textNewline
|
||||
exit 0
|
||||
textNewline
|
||||
textblock "Update ${containerName} container and helper script files"
|
||||
textblock "${bold}Usage: ${localScriptName} [parameters]${norm}"
|
||||
textNewline
|
||||
textblock "If run with no parameters, the script will update both the container and the helper script files, including this update script."
|
||||
textblockHeader " parameters "
|
||||
textblockParam "-h|-?|--help" "Display this help screen."
|
||||
textblockParam "-c|--container|--container-only" "Update the docker container only."
|
||||
textblockParam "-s|--scripts|--scripts-only" "Update the helper scripts (including this update script) only."
|
||||
textNewline
|
||||
exit 0
|
||||
}
|
||||
|
||||
textBlock() {
|
||||
printf "%s\n" "$1" | fold -w "$width" -s
|
||||
textblock() {
|
||||
printf "%s\n" "$1" | fold -w "$width" -s
|
||||
}
|
||||
|
||||
textBlockHeader() {
|
||||
printf "\n%s***%s***%s\n" "$header" "$1" "$norm"
|
||||
textblockHeader() {
|
||||
printf "\n%s***%s***%s\n" "$header" "$1" "$norm"
|
||||
}
|
||||
|
||||
textBlockParam() {
|
||||
printf "%s%-35s%s%s\n" "$info" "$1" "$2" "$norm"
|
||||
textblockParam() {
|
||||
printf "%s%-35s%s%s\n" "$info" "$1" "$2" "$norm"
|
||||
}
|
||||
|
||||
textNewline() {
|
||||
printf "\n"
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
#
|
||||
# text formatting presets
|
||||
### text formatting presets
|
||||
if command -v tput >/dev/null 2>&1; then
|
||||
bold=$(tput bold)
|
||||
err=$(tput bold)$(tput setaf 1)
|
||||
info=$(tput bold)$(tput setaf 6)
|
||||
header=$(tput bold)$(tput setaf 5)
|
||||
norm=$(tput sgr0)
|
||||
ok=$(tput sgr0)$(tput setaf 2)
|
||||
warn=$(tput bold)$(tput setaf 3)
|
||||
width=$(tput cols)
|
||||
bold=$(tput bold)
|
||||
err=$(tput bold)$(tput setaf 1)
|
||||
info=$(tput bold)$(tput setaf 6)
|
||||
header=$(tput bold)$(tput setaf 5)
|
||||
norm=$(tput sgr0)
|
||||
ok=$(tput sgr0)$(tput setaf 2)
|
||||
warn=$(tput bold)$(tput setaf 3)
|
||||
width=$(tput cols)
|
||||
else
|
||||
bold=''
|
||||
err=''
|
||||
info=''
|
||||
header=''
|
||||
norm=''
|
||||
ok=''
|
||||
warn=''
|
||||
width=80
|
||||
bold=''
|
||||
err=''
|
||||
info=''
|
||||
header=''
|
||||
norm=''
|
||||
ok=''
|
||||
warn=''
|
||||
width=80
|
||||
fi
|
||||
|
||||
#
|
||||
# pre-requisites
|
||||
### pre-requisites
|
||||
# check if wget is installed
|
||||
if ! command -v wget >/dev/null 2>&1; then
|
||||
errMsg "Sorry, this script requires that 'wget' is installed in order to download updates. Exiting."
|
||||
errMsg "Sorry, this script requires that 'wget' is installed in order to download updates. Exiting."
|
||||
fi
|
||||
|
||||
# zero counters
|
||||
@ -103,8 +90,8 @@ updateSuccess=0
|
||||
# reference constants
|
||||
dockerNamespace='nginx'
|
||||
containerName='ab-nginx'
|
||||
containerUpdatePath="docker.asifbacchus.dev/$dockerNamespace/$containerName:latest"
|
||||
server="https://asifbacchus.dev/public/docker/$dockerNamespace/$containerName/"
|
||||
containerUpdatePath="docker.asifbacchus.app/$dockerNamespace/$containerName:latest"
|
||||
server="https://asifbacchus.app/updates/docker/$dockerNamespace/$containerName/"
|
||||
checksumFilename='checksums.sha256'
|
||||
|
||||
# operation triggers
|
||||
@ -115,190 +102,149 @@ doScriptUpdate=1
|
||||
localScriptName="$(basename "$0")"
|
||||
repoScriptName='update.sh'
|
||||
|
||||
#
|
||||
# process startup parameters
|
||||
### process startup parameters
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h | -\? | --help)
|
||||
# display inline help
|
||||
scriptHelp
|
||||
;;
|
||||
-s | --scripts | --scripts-only)
|
||||
# update scripts only, skip docker container update
|
||||
doDockerUpdate=0
|
||||
;;
|
||||
-c | --container | --container-only)
|
||||
# update docker container only, skip script update
|
||||
doScriptUpdate=0
|
||||
;;
|
||||
*)
|
||||
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
||||
printf "%sUse '--help' for valid options%s\n\n" "$info" "$norm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
case "$1" in
|
||||
-h | -\? | --help)
|
||||
# display inline help
|
||||
scriptHelp
|
||||
;;
|
||||
-s | --scripts | --scripts-only)
|
||||
# update scripts only, skip docker container update
|
||||
doDockerUpdate=0
|
||||
;;
|
||||
-c | --container | --container-only)
|
||||
# update docker container only, skip script update
|
||||
doScriptUpdate=0
|
||||
;;
|
||||
*)
|
||||
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
||||
printf "%sUse '--help' for valid options%s\n\n" "$info" "$norm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
#
|
||||
# update container
|
||||
### update container
|
||||
if [ "$doDockerUpdate" -eq 1 ]; then
|
||||
# check if docker is installed
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
errMsg "Sorry, it appears that docker is not installed on this machine! Exiting." 2
|
||||
fi
|
||||
# check if docker is installed
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
errMsg "Sorry, it appears that docker is not installed on this machine! Exiting."
|
||||
fi
|
||||
|
||||
# is user root or in the docker group?
|
||||
if [ ! "$(id -u)" -eq 0 ]; then
|
||||
if ! id -Gn | grep docker >/dev/null; then
|
||||
errMsg "You must either be root or in the 'docker' group to pull container updates." 2
|
||||
fi
|
||||
# is user root or in the docker group?
|
||||
if [ ! "$(id -u)" -eq 0 ]; then
|
||||
if ! id -Gn | grep docker >/dev/null; then
|
||||
errMsg "You must either be root or in the 'docker' group to pull container updates."
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "%s\n*** Updating %s container ***\n\n%s" "$info" "$containerName" "$norm"
|
||||
if ! docker pull "$containerUpdatePath"; then
|
||||
errMsg "There was an error updating the container. Try again later." 31
|
||||
else
|
||||
okMsg "Container updated!"
|
||||
fi
|
||||
printf "%s\n*** Updating %s container ***\n\n%s" "$info" "$containerName" "$norm"
|
||||
if ! docker pull "$containerUpdatePath"; then
|
||||
errMsg "There was an error updating the container. Try again later."
|
||||
else
|
||||
okMsg "Container updated!"
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# update scripts
|
||||
### update scripts
|
||||
if [ "$doScriptUpdate" -eq 1 ]; then
|
||||
printf "%s*** Updating %s helper scripts ***%s\n" "$info" "$containerName" "$norm"
|
||||
printf "%s*** Updating %s service scripts ***%s\n" "$info" "$containerName" "$norm"
|
||||
|
||||
## download latest checksums
|
||||
printf "Getting latest checksums... "
|
||||
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
|
||||
errNotify
|
||||
errMsg "Unable to download checksums. Try again later." 41
|
||||
## download latest checksums
|
||||
printf "Getting latest checksums... "
|
||||
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
|
||||
errNotify
|
||||
errMsg "Unable to download checksums. Try again later."
|
||||
else
|
||||
okNotify
|
||||
fi
|
||||
|
||||
## check for updates to this script
|
||||
printf "Checking for updates to this script... "
|
||||
repoScriptChecksum=$(grep "$repoScriptName" "$checksumFilename" | grep -o '^\S*')
|
||||
localScriptChecksum=$(sha256sum "$localScriptName" | grep -o '^\S*')
|
||||
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[NONE]\n"
|
||||
else
|
||||
printf "[AVAILABLE]\n"
|
||||
printf "Getting updated script... "
|
||||
# download updated script
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "update.sh.tmp" "${server}${repoScriptName}"; then
|
||||
errNotify
|
||||
# delete failed download as necessary
|
||||
rm -f ./update.sh.tmp 2>/dev/null
|
||||
errMsg "Unable to download script update. Try again later."
|
||||
else
|
||||
# verify download
|
||||
dlScriptChecksum=$(sha256sum "update.sh.tmp" | grep -o '^\S*')
|
||||
if ! [ "$dlScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[ERROR]\n"
|
||||
# delete corrupt download as necessary
|
||||
rm -f ./update.sh.tmp 2>/dev/null
|
||||
errMsg "Checksum mismatch! Try again later."
|
||||
else
|
||||
okNotify
|
||||
printf "\n%s*** This script has been updated. Please re-run it to load the updated version of this file. ***%s\n\n" "$warn" "$norm"
|
||||
# overwrite this script with updated script
|
||||
mv -f ./update.sh.tmp "$localScriptName"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
## check for updates to this script
|
||||
printf "Checking for updates to this script... "
|
||||
repoScriptChecksum=$(grep "$repoScriptName" "$checksumFilename" | grep -o '^\S*')
|
||||
localScriptChecksum=$(sha256sum "$localScriptName" | grep -o '^\S*')
|
||||
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[NONE]\n"
|
||||
## update files
|
||||
while IFS=' ' read -r field1 field2; do
|
||||
printf "\nChecking '%s' for updates... " "$field2"
|
||||
updateFilename="$field2"
|
||||
repoFileChecksum="$field1"
|
||||
if [ -f "$updateFilename" ]; then
|
||||
localFileChecksum=$(sha256sum "$updateFilename" | grep -o '^\S*')
|
||||
else
|
||||
printf "[AVAILABLE]\n"
|
||||
printf "Getting updated script... "
|
||||
# download updated script
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "update.sh.tmp" "${server}${repoScriptName}"; then
|
||||
errNotify
|
||||
# delete failed download as necessary
|
||||
rm -f ./update.sh.tmp 2>/dev/null
|
||||
errMsg "Unable to download script update. Try again later." 42
|
||||
else
|
||||
# verify download
|
||||
dlScriptChecksum=$(sha256sum "update.sh.tmp" | grep -o '^\S*')
|
||||
if ! [ "$dlScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[ERROR]\n"
|
||||
# delete corrupt download as necessary
|
||||
rm -f ./update.sh.tmp 2>/dev/null
|
||||
errMsg "Checksum mismatch! Try again later." 42
|
||||
else
|
||||
okNotify
|
||||
printf "\n%s*** This script has been updated. Please re-run it to load the updated version of this file. ***%s\n\n" "$warn" "$norm"
|
||||
# overwrite this script with updated script
|
||||
mv -f ./update.sh.tmp "$localScriptName"
|
||||
chmod +x "$localScriptName"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
localFileChecksum=0
|
||||
fi
|
||||
|
||||
## update files
|
||||
makeDirectory "config"
|
||||
makeDirectory "sites"
|
||||
makeDirectory "snippets"
|
||||
|
||||
while IFS=' ' read -r field1 field2; do
|
||||
if [ "$field2" = "update.sh" ]; then continue; fi
|
||||
printf "\nChecking '%s' for updates... " "$field2"
|
||||
updateFilename="$field2"
|
||||
repoFileChecksum="$field1"
|
||||
if [ -f "$updateFilename" ]; then
|
||||
localFileChecksum=$(sha256sum "$updateFilename" | grep -o '^\S*')
|
||||
else
|
||||
localFileChecksum=0
|
||||
fi
|
||||
|
||||
# update file if necessary
|
||||
# update file if necessary
|
||||
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
|
||||
printf "[AVAILABLE]\n"
|
||||
updatesAvailable=$((updatesAvailable + 1))
|
||||
# download update
|
||||
printf "Downloading updated '%s'... " "$updateFilename"
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "$updateFilename.tmp" "${server}${updateFilename}"; then
|
||||
errNotify
|
||||
downloadFailed=$((downloadFailed + 1))
|
||||
# delete failed download file as necessary
|
||||
rm -f "$updateFilename.tmp" 2>&1
|
||||
else
|
||||
okNotify
|
||||
downloadSuccess=$((downloadSuccess + 1))
|
||||
# verify download
|
||||
printf "Verifying '%s'... " "$updateFilename"
|
||||
localFileChecksum=$(sha256sum "$updateFilename.tmp" | grep -o '^\S*')
|
||||
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
|
||||
printf "[AVAILABLE]\n"
|
||||
updatesAvailable=$((updatesAvailable + 1))
|
||||
# download update
|
||||
printf "Downloading updated '%s'... " "$updateFilename"
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "$updateFilename.tmp" "${server}${updateFilename}"; then
|
||||
errNotify
|
||||
downloadFailed=$((downloadFailed + 1))
|
||||
# delete failed download file as necessary
|
||||
rm -f "$updateFilename.tmp" 2>&1
|
||||
else
|
||||
okNotify
|
||||
downloadSuccess=$((downloadSuccess + 1))
|
||||
# verify download
|
||||
printf "Verifying '%s'... " "$updateFilename"
|
||||
localFileChecksum=$(sha256sum "$updateFilename.tmp" | grep -o '^\S*')
|
||||
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
|
||||
errNotify
|
||||
updateFailed=$((updateFailed + 1))
|
||||
# delete corrupted download file as necessary
|
||||
rm -f "$updateFilename.tmp" 2>&1
|
||||
else
|
||||
okNotify
|
||||
updateSuccess=$((updateSuccess + 1))
|
||||
# overwrite old version of file
|
||||
mv -f "$updateFilename.tmp" "$updateFilename"
|
||||
if [ "${updateFilename##*.}" = "sh" ]; then
|
||||
# shell file --> make it executable
|
||||
chmod +x "$updateFilename"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
errNotify
|
||||
updateFailed=$((updateFailed + 1))
|
||||
# delete corrupted download file as necessary
|
||||
rm -f "$updateFilename.tmp" 2>&1
|
||||
else
|
||||
printf "[NONE]\n"
|
||||
okNotify
|
||||
updateSuccess=$((updateSuccess + 1))
|
||||
# overwrite old version of file
|
||||
mv -f "$updateFilename.tmp" "$updateFilename"
|
||||
fi
|
||||
done <"$checksumFilename"
|
||||
fi
|
||||
else
|
||||
printf "[NONE]\n"
|
||||
fi
|
||||
done <"$checksumFilename"
|
||||
fi
|
||||
|
||||
#
|
||||
# display results
|
||||
### display results
|
||||
if [ "$doScriptUpdate" -eq 1 ]; then
|
||||
printf "\n%s*** Results ***%s\n" "$info" "$norm"
|
||||
printf "\tUpdates: %s available\n" "$updatesAvailable"
|
||||
printf "\tDownloads: %s%s successful%s, %s%s failed%s\n" "$ok" "$downloadSuccess" "$norm" "$err" "$downloadFailed" "$norm"
|
||||
printf "\tUpdates: %s%s applied%s, %s%s failed%s\n" "$ok" "$updateSuccess" "$norm" "$err" "$updateFailed" "$norm"
|
||||
printf "\n%s*** Results ***%s\n" "$info" "$norm"
|
||||
printf "\tUpdates: %s available\n" "$updatesAvailable"
|
||||
printf "\tDownloads: %s%s successful%s, %s%s failed%s\n" "$ok" "$downloadSuccess" "$norm" "$err" "$downloadFailed" "$norm"
|
||||
printf "\tUpdates: %s%s applied%s, %s%s failed%s\n" "$ok" "$updateSuccess" "$norm" "$err" "$updateFailed" "$norm"
|
||||
fi
|
||||
|
||||
#
|
||||
# exit
|
||||
if [ "$downloadFailed" -gt 0 ]; then
|
||||
exit 43
|
||||
elif [ "$updateFailed" -gt 0 ]; then
|
||||
exit 44
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
# this is a trap for mis-coding... should never get an exit code 99!
|
||||
exit 99
|
||||
|
||||
#
|
||||
# exit return codes
|
||||
# 0: normal exit, no errors
|
||||
# 1: missing or invalid parameter
|
||||
# 2: docker not found or no docker permissions
|
||||
# 31: unable to update docker container
|
||||
# 4x: helper files errors
|
||||
# 40: unable to make download directories
|
||||
# 41: unable to download checksums
|
||||
# 42: update script: unable to download or bad checksum
|
||||
# 43: update helpers: unable to download
|
||||
# 44: update helpers: bad checksum, no update
|
||||
# 99: coding mistake trap -- this return code should never happen!
|
||||
|
||||
#EOF
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user