浏览代码

Removes the need of a config file and allows db config via environment

chaptergy 5 年之前
父节点
当前提交
57fc1d8f08
共有 7 个文件被更改,包括 172 次插入99 次删除
  1. 0 10
      .jenkins/config-mysql.json
  2. 0 11
      .jenkins/config-sqlite.json
  3. 86 1
      backend/index.js
  4. 10 5
      docker/docker-compose.ci.yml
  5. 10 4
      docker/docker-compose.dev.yml
  6. 9 18
      docs/README.md
  7. 57 50
      docs/setup/README.md

+ 0 - 10
.jenkins/config-mysql.json

@@ -1,10 +0,0 @@
-{
-	"database": {
-		"engine": "mysql",
-		"host": "db",
-		"name": "npm",
-		"user": "npm",
-		"password": "npm",
-		"port": 3306
-	}
-}

+ 0 - 11
.jenkins/config-sqlite.json

@@ -1,11 +0,0 @@
-{
-	"database": {
-		"engine": "knex-native",
-		"knex": {
-			"client": "sqlite3",
-			"connection": {
-				"filename": "/data/database.sqlite"
-			}
-		}
-	}
-}

+ 86 - 1
backend/index.js

@@ -2,7 +2,10 @@
 
 const logger = require('./logger').global;
 
-function appStart () {
+async function appStart () {
+	// Create config file db settings if environment variables have been set
+	await createDbConfigFromEnvironment();
+
 	const migrate             = require('./migrate');
 	const setup               = require('./setup');
 	const app                 = require('./app');
@@ -10,6 +13,7 @@ function appStart () {
 	const internalCertificate = require('./internal/certificate');
 	const internalIpRanges    = require('./internal/ip_ranges');
 
+
 	return migrate.latest()
 		.then(setup)
 		.then(() => {
@@ -39,6 +43,87 @@ function appStart () {
 		});
 }
 
+async function createDbConfigFromEnvironment(){
+	return new Promise((resolve, reject) => {
+		const envMysqlHost  = process.env.DB_MYSQL_HOST;
+		const envMysqlPort  = process.env.DB_MYSQL_PORT;
+		const envMysqlUser  = process.env.DB_MYSQL_USER;
+		const envMysqlName  = process.env.DB_MYSQL_NAME;
+		const envSqliteFile = process.env.DB_SQLITE_FILE;
+		if ((envMysqlHost && envMysqlPort && envMysqlUser && envMysqlName) || envSqliteFile) {
+			const fs       = require('fs');
+			const filename = (process.env.NODE_CONFIG_DIR || './config') + '/' + (process.env.NODE_ENV || 'default') + '.json';
+			let configData = {};
+
+			try {
+				configData = require(filename);
+			} catch (err) {
+				// do nothing
+			}
+
+			if (configData.database && configData.database.engine && !configData.database.fromEnv) {
+				logger.info('Manual db configuration already exists, skipping config creation from environment variables');
+				resolve();
+				return;
+			}
+
+			if (envMysqlHost && envMysqlPort && envMysqlUser && envMysqlName) {
+				const newConfig = {
+					fromEnv:  true,
+					engine:   'mysql',
+					host:     envMysqlHost,
+					port:     envMysqlPort,
+					user:     envMysqlUser,
+					password: process.env.DB_MYSQL_PASSWORD,
+					name:     envMysqlName,
+				};
+
+				if (JSON.stringify(configData.database) === JSON.stringify(newConfig)) {
+					// Config is unchanged, skip overwrite
+					resolve();
+					return;
+				}
+
+				logger.info('Generating MySQL db configuration from environment variables');
+				configData.database = newConfig;
+
+			} else {
+				const newConfig = {
+					fromEnv: true,
+					engine:  'knex-native',
+					knex:    {
+						client:     'sqlite3',
+						connection: {
+							filename: envSqliteFile
+						}
+					}
+				};
+				if (JSON.stringify(configData.database) === JSON.stringify(newConfig)) {
+					// Config is unchanged, skip overwrite
+					resolve();
+					return;
+				}
+
+				logger.info('Generating Sqlite db configuration from environment variables');
+				configData.database = newConfig;
+			}
+
+			// Write config
+			fs.writeFile(filename, JSON.stringify(configData, null, 2), (err) => {
+				if (err) {
+					logger.error('Could not write db config to config file: ' + filename);
+					reject(err);
+				} else {
+					logger.info('Wrote db configuration to config file: ' + filename);
+					resolve();
+				}
+			});
+		} else {
+			// resolve();
+		}
+	});
+}
+
 try {
 	appStart();
 } catch (err) {

+ 10 - 5
docker/docker-compose.ci.yml

@@ -5,11 +5,15 @@ services:
   fullstack-mysql:
     image: ${IMAGE}:ci-${BUILD_NUMBER}
     environment:
-      - NODE_ENV=development
-      - FORCE_COLOR=1
+      NODE_ENV: "development"
+      FORCE_COLOR: 1
+      DB_MYSQL_HOST: "db"
+      DB_MYSQL_PORT: 3306
+      DB_MYSQL_USER: "npm"
+      DB_MYSQL_PASSWORD: "npm"
+      DB_MYSQL_NAME: "npm"
     volumes:
       - npm_data:/data
-      - ../.jenkins/config-mysql.json:/app/config/development.json
     expose:
       - 81
       - 80
@@ -20,8 +24,9 @@ services:
   fullstack-sqlite:
     image: ${IMAGE}:ci-${BUILD_NUMBER}
     environment:
-      - NODE_ENV=development
-      - FORCE_COLOR=1
+      NODE_ENV: "development"
+      FORCE_COLOR: 1
+      DB_SQLITE_FILE: "/data/database.sqlite"
     volumes:
       - npm_data:/data
       - ../.jenkins/config-sqlite.json:/app/config/development.json

+ 10 - 4
docker/docker-compose.dev.yml

@@ -14,10 +14,16 @@ services:
     networks:
       - nginx_proxy_manager
     environment:
-      - NODE_ENV=development
-      - FORCE_COLOR=1
-      - DEVELOPMENT=true
-      #- DISABLE_IPV6=true
+      NODE_ENV: "development"
+      FORCE_COLOR: 1
+      DEVELOPMENT: "true"
+      DB_MYSQL_HOST: "db"
+      DB_MYSQL_PORT: 3306
+      DB_MYSQL_USER: "npm"
+      DB_MYSQL_PASSWORD: "npm"
+      DB_MYSQL_NAME: "npm"
+      # DB_SQLITE_FILE: "/data/database.sqlite"
+      # DISABLE_IPV6: "true"
     volumes:
       - npm_data:/data
       - le_data:/etc/letsencrypt

+ 9 - 18
docs/README.md

@@ -45,21 +45,7 @@ footer: MIT Licensed | Copyright © 2016-present jc21.com
 - [Docker Install documentation](https://docs.docker.com/install/)
 - [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
 
-2. Create a config file for example
-```json
-{
-  "database": {
-    "engine": "mysql",
-    "host": "db",
-    "name": "npm",
-    "user": "npm",
-    "password": "npm",
-    "port": 3306
-  }
-}
-```
-
-3. Create a docker-compose.yml file similar to this:
+2. Create a docker-compose.yml file similar to this:
 
 ```yml
 version: '3'
@@ -70,8 +56,13 @@ services:
       - '80:80'
       - '81:81'
       - '443:443'
+    environment:
+      DB_MYSQL_HOST: "db"
+      DB_MYSQL_PORT: 3306
+      DB_MYSQL_USER: "npm"
+      DB_MYSQL_PASSWORD: "npm"
+      DB_MYSQL_NAME: "npm"
     volumes:
-      - ./config.json:/app/config/production.json
       - ./data:/data
       - ./letsencrypt:/etc/letsencrypt
   db:
@@ -85,13 +76,13 @@ services:
       - ./data/mysql:/var/lib/mysql
 ```
 
-4. Bring up your stack
+3. Bring up your stack
 
 ```bash
 docker-compose up -d
 ```
 
-5. Log in to the Admin UI
+4. Log in to the Admin UI
 
 When your docker container is running, connect to it on port `81` for the admin interface.
 Sometimes this can take a little bit because of the entropy of keys.

+ 57 - 50
docs/setup/README.md

@@ -1,50 +1,5 @@
 # Full Setup Instructions
 
-### Configuration File
-
-**The configuration file needs to be provided by you!**
-
-Don't worry, this is easy to do.
-
-The app requires a configuration file to let it know what database you're using. By default, this file is called `config.json`
-
-Here's an example configuration for `mysql` (or mariadb) that is compatible with the docker-compose example below:
-
-```json
-{
-  "database": {
-    "engine": "mysql",
-    "host": "db",
-    "name": "npm",
-    "user": "npm",
-    "password": "npm",
-    "port": 3306
-  }
-}
-```
-
-Alternatively if you would like to use a Sqlite database file:
-
-```json
-{
-  "database": {
-    "engine": "knex-native",
-    "knex": {
-      "client": "sqlite3",
-      "connection": {
-        "filename": "/data/database.sqlite"
-      }
-    }
-  }
-}
-```
-
-Once you've created your configuration file it's easy to mount it in the docker container.
-
-**Note:** After the first run of the application, the config file will be altered to include generated encryption keys unique to your installation. These keys
-affect the login and session management of the application. If these keys change for any reason, all users will be logged out.
-
-
 ### MySQL Database
 
 If you opt for the MySQL configuration you will have to provide the database server yourself. You can also use MariaDB. Here are the minimum supported versions:
@@ -61,7 +16,6 @@ When using a `mariadb` database, the NPM configuration file should still use the
 
 :::
 
-
 ### Running the App
 
 Via `docker-compose`:
@@ -80,11 +34,18 @@ services:
       # Admin Web Port:
       - '81:81'
     environment:
+      # These are the settings to access your db
+      DB_MYSQL_HOST: "db"
+      DB_MYSQL_PORT: 3306
+      DB_MYSQL_USER: "npm"
+      DB_MYSQL_PASSWORD: "npm"
+      DB_MYSQL_NAME: "npm"
+      # If you would rather use Sqlite uncomment this
+      # and remove all DB_MYSQL_* lines above
+      # DB_SQLITE_FILE: "/data/database.sqlite"
       # Uncomment this if IPv6 is not enabled on your host
       # DISABLE_IPV6: 'true'
     volumes:
-      # Make sure this config.json file exists as per instructions above:
-      - ./config.json:/app/config/production.json
       - ./data:/data
       - ./letsencrypt:/etc/letsencrypt
     depends_on:
@@ -101,14 +62,14 @@ services:
       - ./data/mysql:/var/lib/mysql
 ```
 
+_Please note, that `DB_MYSQL_*` environment variables will take precedent over `DB_SQLITE_*` variables. So if you keep the MySQL variables, you will not be able to use Sqlite._
+
 Then:
 
 ```bash
 docker-compose up -d
 ```
 
-The config file (config.json) must be present in this directory.
-
 ### Running on Raspberry PI / ARM devices
 
 The docker images support the following architectures:
@@ -146,3 +107,49 @@ Password: changeme
 ```
 
 Immediately after logging in with this default user you will be asked to modify your details and change your password.
+
+### Configuration File
+
+::: warning
+
+This section is meant for advanced users
+
+:::
+
+If you would like more control over the database settings you can define a custom config JSON file.
+
+
+Here's an example for `sqlite` configuration as it is generated from the environment variables:
+
+```json
+{
+  "database": {
+    "engine": "knex-native",
+    "knex": {
+      "client": "sqlite3",
+      "connection": {
+        "filename": "/data/database.sqlite"
+      }
+    }
+  }
+}
+```
+
+You can modify the `knex` object with your custom configuration, but note that not all knex clients might be installed in the image.
+
+Once you've created your configuration file you can mount it to `/app/config/production.json` inside you container using:
+
+```
+[...]
+services:
+  app:
+    image: 'jc21/nginx-proxy-manager:latest'
+    [...]
+    volumes:
+      - ./config.json:/app/config/production.json
+      [...]
+[...]
+```
+
+**Note:** After the first run of the application, the config file will be altered to include generated encryption keys unique to your installation.
+These keys affect the login and session management of the application. If these keys change for any reason, all users will be logged out.