Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
bubbajames-docker committed Jul 19, 2020
0 parents commit 8161b96
Show file tree
Hide file tree
Showing 11 changed files with 514 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
49 changes: 49 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# Docker with Sendy Email Campaign Marketing
#
# Build:
# $ docker build -t sendy:latest -f ./Dockerfile .
#
# Run:
# $ docker run --rm -d sendy:latest

FROM php:7.4.8-apache

ARG SENDY_VER=4.1.0

ENV SENDY_VERSION ${SENDY_VER}

RUN apt -qq update && apt -qq upgrade -y \
# Install unzip
&& apt -qq install -y unzip \
# Install php extension gettext
# Install php extension mysqli
&& docker-php-ext-install gettext mysqli \
# Remove unused packages
&& apt autoremove -y

# Copy artifacts
COPY ./artifacts/${SENDY_VER}/ /tmp

# Install Sendy
RUN unzip /tmp/sendy-${SENDY_VER}.zip -d /tmp \
&& mv /tmp/config.php /tmp/sendy/includes \
&& chmod 777 /tmp/sendy/uploads \
&& rm -rf /var/www/html \
&& mv /tmp/sendy /var/www/html \
&& rm -rf /tmp/* \
&& echo "\nServerName \${SENDY_FQDN}" > /etc/apache2/conf-available/serverName.conf \
# Ensure X-Powered-By is always removed regardless of php.ini or other settings.
&& printf "\n\n# Ensure X-Powered-By is always removed regardless of php.ini or other settings.\n\
Header always unset \"X-Powered-By\"\n\
Header unset \"X-Powered-By\"\n" >> /var/www/html/.htaccess

# Apache config
RUN a2enconf serverName

# Apache modules
RUN a2enmod rewrite headers

COPY artifacts/docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["apache2-foreground"]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 bubbajames-docker

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.
159 changes: 159 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Quick reference
This is the unofficial Sendy docker repository.

<a href="https://sendy.co/?ref=Hcurv" title=""><img src="https://sendy.co/images/banners/728x90_var2.jpg" alt="Check out Sendy, a self hosted newsletter app that lets you send emails 100x cheaper via Amazon SES." width="728" height="90"/></a>

* Maintained by: [the Sendy Community](https://sendy.co/forum)

* Where to get help: [the Sendy Troubleshooting & Support Guide](https://sendy.co/troubleshooting), [the Sendy Community Forums](https://sendy.co/forum)

* License Required: [Purchasing details](https://sendy.co/?ref=Hcurv)

# Supported tags and respective Dockerfile links
* `4.1.0` `4.1` `4` `latest`

# Quick reference (cont.)
* Where to file docker-related issues: [https://github.com/bubbajames-docker/sendy](https://github.com/bubbajames-docker/sendy)

* Where to file Send application issues: see [the Sendy Troubleshooting & Support Guide](https://sendy.co/troubleshooting)

# What is Sendy?
Sendy is a self-hosted email newsletter application that lets you send trackable emails via [Amazon Simple Email Service (SES)](http://aws.amazon.com/ses/). This makes it possible for you to send authenticated bulk emails at an insanely low price without sacrificing deliverability.

For more information and related downloads for Sendy Server and other products, please visit [Send.co](https://sendy.co/?ref=Hcurv).

<a href="https://sendy.co/?ref=Hcurv" title=""><img src="https://sendy.co/images/banners/125x125_var2.jpg" alt="Check out Sendy, a self hosted newsletter app that lets you send emails 100x cheaper via Amazon SES." width="125" height="125"/></a>

# How to use this image
Starting a Sendy instance is simple.

```console
$ docker run -d \
--name sendy \
-e SENDY_FQDN=campaigns.example.com \
-e MYSQL_HOST=db_sendy \
-e MYSQL_PASSWORD=db_password \
bubbajames/sendy:tag
```
... where `sendy` is the name you want to assign to your container, `campaigns.example.com` is your FQDN of Sendy server, `db_sendy` is your database server instance, `db_password` is the database user's password and `tag` is the tag specifying the Sendy version you want. See the list of tags above.

## Environment Varaibles
### `SENDY_FQDN` (required)
The fully qualified domain name of your Sendy installation. This must match the FQDN associated with your license. You can [purchase a license here](https://sendy.co/?ref=Hcurv).
### `MYSQL_HOST` (required)
The MySQL server hosting your Sendy database.
### `MYSQL_DATABASE` (optional)
The Sendy database name. Default: `sendy`.
### `MYSQL_USER` (optional)
Database user. Default: `sendy`.
### `MYSQL_PASSWORD` (required)
Database user's password. Not recommended for sensitive data! (see: Docker Secrets)

## Docker Secrets
As an alternative to passing sensitive information via environment variables, `_FILE` may be appended to the previously listed environment variables, causing the initialization script to load the values for those variables from files present in the container. In particular, this can be used to load passwords from Docker secrets stored in /run/secrets/\<secret_name> files.

For example:

```console
$ docker run -d --name sendy -e MYSQL_PASSWORD_FILE=/run/secrets/mysql-root -d sendy
```

## Using `Dockerfile`
Pretty minimalistic `Dockerfile` as everything you need is already bundled. Just provide environment variables or environment file.

```dockerfile
FROM bubbajames/sendy:4.1

# ... whatever you want here.
```
### Start a Sendy instance
The following starts an instance specifying an environment file.

```console
$ docker run -d -name sendy --env_file sendy.env sendy
```

### Sample environment file
```ini
SENDY_FQDN=campaigns.example.com
MYSQL_HOST=db_sendy
MYSQL_DATABASE=sendy
MYSQL_USER=sendy
MYSQL_PASSWORD_FILE=/run/secrets/db_password
# MYSQL_PASSWORD=db_password
```

## Using `docker-compose`
Starts a Send instance and a MySQL database instance with mounted volume for persisted data between restarts. Also uses Docker Secrets to avoid exposing sensitive data via 'inspect'.

The following `docker-compose.yml` is also available from image [repository](https://raw.githubusercontent.com/bubbajames-docker/sendy/master/docker-compose.yml).

```yaml
version: "3.7"

# Volumes for persisted data.
volumes:
data_sendy:
labels:
co.sendy.description: "Data volume for Sendy Database."

# Secret files so they're not exposed via 'docker inspect'
secrets:
db_password:
file: secrets/db_password.txt
db_root_password:
file: secrets/db_root_password.txt

services:
# Database: MySQL
db_sendy:
hostname: db_sendy
container_name: db_sendy
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: sendy
MYSQL_USER: sendy
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
volumes:
- data_sendy:/var/lib/mysql

# WebApp: Apache2+PHP+Sendy
sendy:
hostname: sendy
container_name: sendy
depends_on:
- db_sendy
image: sendy:latest
build:
context: .
environment:
SENDY_FQDN: campaigns.example.com
MYSQL_HOST: db_sendy
MYSQL_DATABASE: sendy
MYSQL_USER: sendy
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
ports:
- 80:80
```
### Start the services
```console
$ docker-compose up -d
```
### Stop the services
```console
$ docker-compose down
```

# License

Please [see license](https://raw.githubusercontent.com/bubbajames-docker/sendy/master/LICENSE) in repository

As with all Docker images, these likely also contain other software that may be under other licenses (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained).

As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.
32 changes: 32 additions & 0 deletions artifacts/4.1.0/includes/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
//----------------------------------------------------------------------------------//
// COMPULSORY SETTINGS
//----------------------------------------------------------------------------------//

/* Set the URL to your Sendy installation (without the trailing slash) */
define('APP_PATH', 'http://' . getenv('SENDY_FQDN'));

/* MySQL database connection credentials (please place values between the apostrophes) */
$dbHost = getenv('MYSQL_HOST'); //MySQL Hostname
$dbUser = getenv('MYSQL_USER'); //MySQL Username
$dbPass = getenv('MYSQL_PASSWORD'); //MySQL Password
$dbName = getenv('MYSQL_DATABASE'); //MySQL Database Name


//----------------------------------------------------------------------------------//
// OPTIONAL SETTINGS
//----------------------------------------------------------------------------------//

/*
Change the database character set to something that supports the language you'll
be using. Example, set this to utf16 if you use Chinese or Vietnamese characters
*/
$charset = 'utf8mb4';

/* Set this if you use a non standard MySQL port. */
$dbPort = (!empty(getenv('SENDY_DB_PORT')) ? getenv('SENDY_DB_PORT') : 3306);

/* Domain of cookie (99.99% chance you don't need to edit this at all) */
define('COOKIE_DOMAIN', '');

//----------------------------------------------------------------------------------//
75 changes: 75 additions & 0 deletions artifacts/4.1.0/includes/main.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
//------------------------------------------------------//
// INIT //
//------------------------------------------------------//

include('../functions.php');

$email = mysqli_real_escape_string($mysqli, $_POST['email']);
$pass = mysqli_real_escape_string($mysqli, $_POST['password']);
$pass_encrypted = hash('sha512', $pass . 'PectGtma');
if (isset($_POST['redirect'])) $redirect_to = $_POST['redirect'];
else $redirect_to = '';
$time = time();

//------------------------------------------------------//
// EVENTS //
//------------------------------------------------------//
if ($pass == '' || $email == '') {
//user doesn't exist and exit
if ($redirect_to == '') header("Location: " . get_app_info('path') . "/login?e=1");
else header("Location: " . get_app_info('path') . "/login?e=1&redirect=$redirect_to");
exit;
} else {
//If logging in using brand's custom domain URL
if (CURRENT_DOMAIN != APP_PATH_DOMAIN) {
//Get app id
$q = 'SELECT id FROM apps WHERE custom_domain = "' . CURRENT_DOMAIN . '"';
$r = mysqli_query($mysqli, $q);
if ($r && mysqli_num_rows($r) > 0) while ($row = mysqli_fetch_array($r)) $app_id = $row['id'];
$app_id_line = (!empty($app_id) ? 'AND app = ' . $app_id : null);
}
$q = 'SELECT id, tied_to, app, auth_enabled, auth_key FROM login WHERE username = "' . $email . '" AND password = "' . $pass_encrypted . '" ' . $app_id_line . ' ORDER BY id ASC LIMIT 1';
$r = mysqli_query($mysqli, $q);
if ($r && mysqli_num_rows($r) > 0) {
while ($row = mysqli_fetch_array($r)) {
$userID = $row['id'];
$tied_to = $row['tied_to'];
$auth_enabled = $row['auth_enabled'];
$_SESSION['auth_key'] = $row['auth_key'];
$_SESSION['restricted_to_app'] = $row['app'];
$_SESSION['userID'] = $userID;
}

//Reset any pending password requests
$q2 = 'UPDATE login SET reset_password_key = "" WHERE id = ' . $userID;
mysqli_query($mysqli, $q2);

//If 2FA enabled
if ($auth_enabled) {
$_SESSION['cookie'] = hash('sha512', $userID . $email . $pass_encrypted . 'PectGtma');
if ($tied_to == '') {
if ($redirect_to == '') header("Location: " . get_app_info('path') . '/two-factor');
else header("Location: " . get_app_info('path') . '/two-factor?redirect=' . $redirect_to);
} else {
if ($redirect_to == '') header("Location: " . get_app_info('path') . "/two-factor?redirect=app?i=" . $_SESSION['restricted_to_app']);
else header("Location: " . get_app_info('path') . "/two-factor?redirect=" . $redirect_to);
}
}
//set cookie and log in
else if (setcookie('logged_in', hash('sha512', $userID . $email . $pass_encrypted . 'PectGtma'), time() + 31556926, '/', get_app_info('cookie_domain'))) {
if ($tied_to == '') {
if ($redirect_to == '') header("Location: " . get_app_info('path'));
else header("Location: " . get_app_info('path') . '/' . $redirect_to);
} else {
if ($redirect_to == '') header("Location: " . get_app_info('path') . "/app?i=" . $_SESSION['restricted_to_app']);
else header("Location: " . get_app_info('path') . "/" . $redirect_to);
}
}
} else {
//user doesn't exist and exit
if ($redirect_to == '') header("Location: " . get_app_info('path') . "/login?e=2");
else header("Location: " . get_app_info('path') . "/login?e=2&redirect=$redirect_to");
exit;
}
}
Binary file added artifacts/4.1.0/sendy-4.1.0.zip
Binary file not shown.
Loading

0 comments on commit 8161b96

Please sign in to comment.