diff --git a/.gitignore b/.gitignore index 46b5a1a..b874962 100644 --- a/.gitignore +++ b/.gitignore @@ -1,64 +1,14 @@ # Logs -logs *.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release # Dependency directories node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ # Optional npm cache directory .npm -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - # dotenv environment variables file -.env - -# next.js build output -.next +app/.env #postgres stuff postgresql diff --git a/index.js b/app/index.js similarity index 78% rename from index.js rename to app/index.js index be3b85b..286d699 100755 --- a/index.js +++ b/app/index.js @@ -4,30 +4,23 @@ * Module dependencies. */ -import app from './app.js'; +import app from './server/app.js'; import debug from 'debug'; debug('pathtoglory:server'); -import https from 'https'; -import path from 'node:path'; -import fs from 'node:fs'; - -const sslOptions = { - key: fs.readFileSync(path.join(import.meta.dirname, 'localhost-key.pem')), - cert: fs.readFileSync(path.join(import.meta.dirname, 'localhost.pem')) -}; +import http from 'http'; /** * Get port from environment and store in Express. */ -var port = normalizePort(process.env.PORT || '1234'); +var port = normalizePort(process.env.PORT); app.set('port', port); +app.set('trust proxy', true); /** * Create HTTP server. */ - -var server = https.createServer(sslOptions, app); +var server = http.createServer(app); /** * Listen on provided port, on all network interfaces. diff --git a/package-lock.json b/app/package-lock.json similarity index 100% rename from package-lock.json rename to app/package-lock.json diff --git a/package.json b/app/package.json similarity index 100% rename from package.json rename to app/package.json diff --git a/public/favicon.ico b/app/public/favicon.ico similarity index 100% rename from public/favicon.ico rename to app/public/favicon.ico diff --git a/public/javascripts/user-login.js b/app/public/javascripts/user-login.js similarity index 100% rename from public/javascripts/user-login.js rename to app/public/javascripts/user-login.js diff --git a/public/javascripts/users.js b/app/public/javascripts/users.js similarity index 100% rename from public/javascripts/users.js rename to app/public/javascripts/users.js diff --git a/public/stylesheets/style.css b/app/public/stylesheets/style.css similarity index 100% rename from public/stylesheets/style.css rename to app/public/stylesheets/style.css diff --git a/app.js b/app/server/app.js similarity index 81% rename from app.js rename to app/server/app.js index ca04a7d..9647c45 100644 --- a/app.js +++ b/app/server/app.js @@ -8,30 +8,29 @@ import indexRouter from './routes/index.js'; import usersRouter from './routes/users.js'; import postsRouter from './routes/posts.js'; -const __dirname = import.meta.dirname; var app = express(); // view engine setup -app.set('views', path.join(__dirname, 'views')); +app.set('views', path.join(import.meta.dirname, 'views')); app.set('view engine', 'pug'); app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(import.meta.dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter); app.use('/posts', postsRouter); // catch 404 and forward to error handler -app.use(function(req, res, next) { +app.use(function(_, _, next) { next(createError(404)); }); // error handler -app.use(function(err, req, res, next) { +app.use(function(err, req, res) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; diff --git a/controllers/Post.controller.js b/app/server/controllers/Post.controller.js similarity index 100% rename from controllers/Post.controller.js rename to app/server/controllers/Post.controller.js diff --git a/db/index.js b/app/server/db/index.js similarity index 91% rename from db/index.js rename to app/server/db/index.js index d6ca42a..b8d7a71 100644 --- a/db/index.js +++ b/app/server/db/index.js @@ -4,7 +4,7 @@ const db = new Pool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, - port: process.env.PORT, + port: process.env.DB_PORT, database: process.env.DB_DATABASE, max: 20, idleTimeoutMillis: 30_000, diff --git a/db/migrate.js b/app/server/db/migrate.js similarity index 100% rename from db/migrate.js rename to app/server/db/migrate.js diff --git a/db/migrations/2026-02-22_18:00_create_blog_tables.sql b/app/server/db/migrations/2026-02-22_18:00_create_blog_tables.sql similarity index 83% rename from db/migrations/2026-02-22_18:00_create_blog_tables.sql rename to app/server/db/migrations/2026-02-22_18:00_create_blog_tables.sql index c378c7c..a8607d2 100644 --- a/db/migrations/2026-02-22_18:00_create_blog_tables.sql +++ b/app/server/db/migrations/2026-02-22_18:00_create_blog_tables.sql @@ -1,4 +1,4 @@ -CREATE XTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE posts ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), diff --git a/db/migrations/2026-03-04_15:23_create_user_tables.sql b/app/server/db/migrations/2026-03-04_15:23_create_user_tables.sql similarity index 100% rename from db/migrations/2026-03-04_15:23_create_user_tables.sql rename to app/server/db/migrations/2026-03-04_15:23_create_user_tables.sql diff --git a/middlewares/authentication.js b/app/server/middlewares/authentication.js similarity index 100% rename from middlewares/authentication.js rename to app/server/middlewares/authentication.js diff --git a/middlewares/limitedUsers.js b/app/server/middlewares/limitedUsers.js similarity index 100% rename from middlewares/limitedUsers.js rename to app/server/middlewares/limitedUsers.js diff --git a/routes/index.js b/app/server/routes/index.js similarity index 100% rename from routes/index.js rename to app/server/routes/index.js diff --git a/routes/posts.js b/app/server/routes/posts.js similarity index 100% rename from routes/posts.js rename to app/server/routes/posts.js diff --git a/routes/users.js b/app/server/routes/users.js similarity index 100% rename from routes/users.js rename to app/server/routes/users.js diff --git a/views/conclave.pug b/app/server/views/conclave.pug similarity index 100% rename from views/conclave.pug rename to app/server/views/conclave.pug diff --git a/views/error.pug b/app/server/views/error.pug similarity index 100% rename from views/error.pug rename to app/server/views/error.pug diff --git a/views/index.pug b/app/server/views/index.pug similarity index 100% rename from views/index.pug rename to app/server/views/index.pug diff --git a/views/layout.pug b/app/server/views/layout.pug similarity index 100% rename from views/layout.pug rename to app/server/views/layout.pug diff --git a/views/post.pug b/app/server/views/post.pug similarity index 100% rename from views/post.pug rename to app/server/views/post.pug diff --git a/views/users/login.pug b/app/server/views/users/login.pug similarity index 100% rename from views/users/login.pug rename to app/server/views/users/login.pug diff --git a/views/users/register.pug b/app/server/views/users/register.pug similarity index 100% rename from views/users/register.pug rename to app/server/views/users/register.pug diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..20eabe5 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,61 @@ +services: + app: + image: node:krypton-alpine + user: "node" + restart: no + depends_on: + - db + working_dir: /home/node/app + volumes: + - ./app:/home/node/app + develop: + watch: + - path: ./app/server + action: sync+restart + target: /home/node/app/server + - path: ./app/public + action: sync + target: /home/node/app/public + command: node --env-file=.env ./index.js + networks: + - app-network + + db: + image: postgres + restart: always + environment: + POSTGRES_PASSWORD: example + POSTGRES_USER: myuser + POSTGRES_DB: pathtoglory + volumes: + - pgdata:/home/arthur/sources/node/pathtoglory/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready"] + interval: 1s + timeout: 5s + retries: 10 + ports: + - "5432:5432" + networks: + - app-network + + nginx: + image: nginx + ports: + - "8080:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/ssl:/etc/nginx/ssl:ro + depends_on: + - app + networks: + - app-network + + +networks: + app-network: + driver: bridge + +volumes: + pgdata: diff --git a/entities/post/Post.model.js b/entities/post/Post.model.js deleted file mode 100644 index 02eadee..0000000 --- a/entities/post/Post.model.js +++ /dev/null @@ -1,16 +0,0 @@ -export default class Post { - id; - title; - content; - created_at; - updated_at; - - constructor(data) { - this.title = data.title; - this.content = data.content; - - this.id = data.id || undefined; - this.created_at = data.created_at || undefined; - this.updated_at = data.updated_at || undefined; - } -} diff --git a/localhost-key.pem b/localhost-key.pem deleted file mode 100644 index a1cd2df..0000000 --- a/localhost-key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCiYoJCZdHcVH/w -GFQZUhY59jxiJ6GlKbo2cu7ozp34WYyIKun5cPXyWxWUtY0yuf6jUd8+JtL/T0uo -6qBMdnznE8uP0Ol7XmiozZ156celbbhO4VFUDu0wesXGktAPQllmIF7tB3zUhb2R -6PUao8lzn/Um6kLD7FFriTqOJL4X2d9cpAVpvTmjl5YqNRwiPQPOhPH1yyOv6iin -aRjklk00krWlp1Ezd4gitTqzMdGc72cUIVvC3JWLFUUHG4Xjkl7va4FPWCz6P7Di -kq3gadnOE+sWuQNNyVEjnU4hwTUZ8AYEVM23Siq2+7IkKu/oiX+zeBCfZhLNgilf -eTMxxUyhAgMBAAECggEAReo1/VKLhdrX7s76vqAqM7CCFRzNKyiJJVJc7N2xBDHC -IQqhDKYHLt7qrslwTsvoB/eDL+ZVaFmC0OqcM++8HV3XgkdHj7d5RlypFcmDDQXt -mgDHHHMEyp/BsZqafEdr6F29oT5dD7+5fC4aAetNHDxdt/Ca6HJCKBPAo1zMf8W+ -HXepvb3eTTIDG+msclY9b6gCPxuJU3rM+JzkohwClQJJe40lBu4qyMeiGYynjHY2 -/98M21dja02RFBP66S+S9UaPQ5/h1LRMz2vI+njX3qgAWjdTsazoa0jzZsqbIl/u -6NnGlScIGDAQaBpkb2YhhCJxR7Q3f9PGd2leGo1zsQKBgQDITbw05KaKU1hZ0R+0 -196rurSUDbsFmamwFouzRWSwTCMwJlGcoMQ0mChfwwWKAXiNJRlMf0biywIGZisD -CApjgpRNuOdIqy3rU4iDVxwj45XNNgobfF1ZKAHum5q9KjIchUZsI8htC7KgH0S6 -zMsPbxk56ueKGXF6kyZpoW4Z1QKBgQDPiZYkPyk153J72O+V+kwOTOdGoBMETXdY -wPf8gd/j5oNwuQV7DWxMyq4ku4uc9fJn9rAxymHlbFqWce8h2jYVPOfak0Om6N2z -IDjlLKWzvjzpiUNZ8QsODfm4rFYni3sEhC0K3IkDzEDtSr3UakL66Uqjsqg4cn7S -Ik4u0r8hnQKBgQCq+l/7LmpSjQ5PrMjJz7LNGBRohMft4dsM6lHZdxSZwIQQ58Sm -VDznQDLGe2xQ/yxuHwrXV5WkpfFWkQOKFOT5SE9bgMg8KZKK28Udh9AHeo82mjhK -egAcyJ/Nk5mke05HNiSEzo6ZNnEFaWt7oLB8vjLkU3XNViadoNobNKcM+QKBgAku -KeESli0XPt4xm2+D8edUCYr7O7wd/SCE8LNPv2qiYMAUvyRRVLAU6x0e2q8nxgBJ -TkP1kt0GLP+orI5Py8Kmvg7SItT4Sg5JZ5rjnbTUvncKJluNKRMHFTvRC8KWDewG -OMPZO4pad6jHfJwv0ySsOywAlCZjEi8Ta2fw1JmVAoGASSUtaNsjsTJ5ikRXPZTQ -MS0Vb+leH5+M9umbV4sxqsY4oz6l3Dv7fEdigJmrrBTKlH5uRKFxqE91FcOYbyH4 -C9HyzJgiujvfWoFqF5H0EoIpsHvtydGMr+JkHbwDSZfeRelFnUEFLhTQSu/fyHeW -FX/eT/HtOo4D1NKZ5UDG1O8= ------END PRIVATE KEY----- diff --git a/localhost.pem b/localhost.pem deleted file mode 100644 index e3890ab..0000000 --- a/localhost.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID/jCCAmagAwIBAgIRAIckhgeUs09k09IblD8x28EwDQYJKoZIhvcNAQELBQAw -VTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRUwEwYDVQQLDAxhcnRo -dXJAYmVhY2gxHDAaBgNVBAMME21rY2VydCBhcnRodXJAYmVhY2gwHhcNMjYwMzA0 -MTY0OTQwWhcNMjgwNjA0MTU0OTQwWjBAMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxv -cG1lbnQgY2VydGlmaWNhdGUxFTATBgNVBAsMDGFydGh1ckBiZWFjaDCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJigkJl0dxUf/AYVBlSFjn2PGInoaUp -ujZy7ujOnfhZjIgq6flw9fJbFZS1jTK5/qNR3z4m0v9PS6jqoEx2fOcTy4/Q6Xte -aKjNnXnpx6VtuE7hUVQO7TB6xcaS0A9CWWYgXu0HfNSFvZHo9RqjyXOf9SbqQsPs -UWuJOo4kvhfZ31ykBWm9OaOXlio1HCI9A86E8fXLI6/qKKdpGOSWTTSStaWnUTN3 -iCK1OrMx0ZzvZxQhW8LclYsVRQcbheOSXu9rgU9YLPo/sOKSreBp2c4T6xa5A03J -USOdTiHBNRnwBgRUzbdKKrb7siQq7+iJf7N4EJ9mEs2CKV95MzHFTKECAwEAAaNe -MFwwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQY -MBaAFNLXA4V6orI5Z7VVA/5i5ga0AjShMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAN -BgkqhkiG9w0BAQsFAAOCAYEAqJ/+hvJ/xFQ7GBzPteLNcfBtfokSJ5siynMokU3b -mOoKl+jR9r+4/X5aaSe5sOXAaE0kB3dliYxF9J4FMa5y4E5yluYAdt6vFYOI2u4/ -zOuo1VStMhkStXc8h41jd2jfApoiZaicQYv8LwdJ34oHNq+phbUmxxggFLSd2tsD -oaVKUjMe15QvI8HsB+czmpPJUMO8u9ajHUxJZOKyYvTOjdefGMpjEhUpBwOCcFxd -TTybDD/+FmV3h/0m1U0CVrK+TN+hGje97DNK+bV7OxYL/RhoCFm99TOdKJxmV78X -AEIVb6360GVo7ySWxsFRXHu3vzBBoDPwWIieEksqCyfA7jhkaCKRVWZLmwUl4lrg -wGBYJCzibjFZihlgslGAavxBk1cL2Eu5KANkp+ybmP4assbzoXrTZGfY3Va10q3r -5u8oovVVTcVlthVGjpP90qSBogwdlDjtDYFq8PpTyIcqJQTneJ/F4KDf9gawOSqF -1KEt58J/uzK159CrXzJVIXJq ------END CERTIFICATE----- diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..957a369 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,48 @@ +events { + worker_connections 1024; +} + +http { + # Upstream definitions for load balancing + upstream app_servers { + server app:3000; + } + + # Redirect HTTP to HTTPS + server { + listen 80; + server_name localhost; + return 301 https://$server_name$request_uri; + } + + # HTTPS server + server { + listen 443 ssl; + http2 on; + server_name localhost; + + # SSL certificates + ssl_certificate /etc/nginx/ssl/nginx.crt; + ssl_certificate_key /etc/nginx/ssl/nginx.key; + + # SSL settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000" always; + add_header X-Content-Type-Options nosniff; + add_header X-Frame-Options DENY; + + location / { + proxy_pass http://app_servers; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} diff --git a/nginx/ssl/nginx.crt b/nginx/ssl/nginx.crt new file mode 100644 index 0000000..e554bd4 --- /dev/null +++ b/nginx/ssl/nginx.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIURlHl95jmWHmHnnvNTxkY7kW4wtowDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5 +MQwwCgYDVQQKDANPcmcxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNjAzMTIxNjE4 +NTJaFw0yNzAzMTIxNjE4NTJaME4xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0 +ZTENMAsGA1UEBwwEQ2l0eTEMMAoGA1UECgwDT3JnMRIwEAYDVQQDDAlsb2NhbGhv +c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWUpy/ZcJadapNmSGx +tDJpg8e2/KCh4T7iUh90i9g4xZ+0Aq61GXs6pjemTQ11Pq2vW+g2+Ax9Ah98MbW7 +cGNiRZknG9aiIez2FXBjx6MyPmXtvWu57VHbom7rHbASxJmo1hFovbgIlxYL9CKK +PydW8LmvDg3Umfx4PAwRGTJzExI78OZDhBCA+0hFRagWH4jbmjPHJtjavImBSUCr +3V4DdOuS0zcg702Iw/JWPWHpayebziE3DwgKx0h8Szowtk1ElylNUYqC+bRPL0xc +aUY7IwfNdqDq8k/KRq06GKkdfAGVI5/UW9Vg2HuTVj8URyR9mMOPH82cG/FLju0A +fe4dAgMBAAGjUzBRMB0GA1UdDgQWBBSdAtYn/aiQ2VWu5YxaNJfukI5OqTAfBgNV +HSMEGDAWgBSdAtYn/aiQ2VWu5YxaNJfukI5OqTAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQAMTEpQK2asxSBQiGFl1fI1SLycOE1LAu6Fzh/1rzOY +5LRRiLrFbp1DUYvdQvLSDKIztQnFGpZ94ZopZ6ynNbWNJwuZdb1qj6aQ1fEknal1 +pl2wAf+8raGbs/3GDYd0YaVzTlACsPX/DaUj2tchaxlsQaHdRhsz/PHaKPi6AXQk +fYh+sfHgFX4ZmCi5SieGxak/tU7635R1cF+2j8lbepqkbTYgbPVJCH5VmQp0Jp41 +m9OfrH2hgEziFGmadlMd5fMmY4GjWJ/kBixKyXbDM1F+IF3q/kbeIYa1DpG0evgi +keWOA9rdsmxOBJnQTHzfP3PADbBDhpduh6nASBeGsZ19 +-----END CERTIFICATE----- diff --git a/nginx/ssl/nginx.key b/nginx/ssl/nginx.key new file mode 100644 index 0000000..f94fa1f --- /dev/null +++ b/nginx/ssl/nginx.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCWUpy/ZcJadapN +mSGxtDJpg8e2/KCh4T7iUh90i9g4xZ+0Aq61GXs6pjemTQ11Pq2vW+g2+Ax9Ah98 +MbW7cGNiRZknG9aiIez2FXBjx6MyPmXtvWu57VHbom7rHbASxJmo1hFovbgIlxYL +9CKKPydW8LmvDg3Umfx4PAwRGTJzExI78OZDhBCA+0hFRagWH4jbmjPHJtjavImB +SUCr3V4DdOuS0zcg702Iw/JWPWHpayebziE3DwgKx0h8Szowtk1ElylNUYqC+bRP +L0xcaUY7IwfNdqDq8k/KRq06GKkdfAGVI5/UW9Vg2HuTVj8URyR9mMOPH82cG/FL +ju0Afe4dAgMBAAECggEAAVB1mGLOYTYYKBeHqOMXcb66N0pcKS4r+5SWO9GhMVXh +AJTpbCHt5uRfJjAURwsmP5tBG4HtsgYbul1A5oOkCs7q+OGQbdh4Fuq3EdhEAAN1 +pq96SqTdi1sPNzUKPg/D/Crq+gx2mHSht7cJukW1FViDdxlbW5mBEJgNzvR2cXUc +zAmVyyWF4YQEwb4Iinpyy3wm63+Z49dmBigsavp2lkLW3rcE3JG7Q2jYEkvDyOux ++ankDd4lsxfXWW1rDBLwiK00TZQ4gqM/RRDTXCWxi0E82pq5tjG0Cj0R/4wTe4da +eZjXprU03GfQ9FA186hA8wJcUR1IukBhhZcidNE6jQKBgQDK4QDCPufMx6pTeNz4 +TwfowOms2vuMIHAagAwoYpuukL5PD02bjMOVx1IwMwgauATIT/Gl+8psF6KVkSsT +QiMew1apLqVXAq5YHicpi2atT6z5hV+CjAt3wLzpGcVFDklpGW1f6ALmw/p29tJg +TWquWaqRlrd/EPqR10HH0qbvbwKBgQC9rsKlQTrbKYAxOCyxVhBa4muLGYHMwN8I +5I6Y43Ihf3qvejB2rkPrEkMUR+qhlNDAFdybgcSUP0y17QQ9f1Wz0HKMR4qnRzdL +981rNJ3D1ThaTaO13LSzbZDPBQobaYTMxxMRNpM0e4DtxKaZlhI/9qsIp7hZeTYG +j0LZP9n1MwKBgGo63rbXUXC8q8cBZlLurumE+dZ043pAEfMOUU9kMrh5Oe0TykNE +tbTbpYFvdzLmYDqzAYk0Co4G4i8G0FNJMjKNffcgYZrp4HhrcX4jbCQbsCsHVzd4 +NRkDZud3gv/htza9BbROPBaxT5izLP0YDGA2u0V4caSrM0jiOaNz/c0pAoGAb2sY +KroGOHZINqEon4JOWRRm125EMGGaoT6gBG6Vu9eF2U2M6imy+4HepSsZR5CCjlJJ +I482SV5lUPfIZddGIDlxD7V2XIwYjycgIrjlcwLr9x9j6o+aFUtmpDPxm+h/eUn2 +iUXlcg6ZzRCWS+E7Fxdtn8flIalxcqj0O2imPsECgYAPtq9N//2YgNeNsljLzUqf +4K4eC9mvgKhrlfxSIxcnU6cdftV4Q+6UpWH8rB6+/jBYKsR/fYHlWwDdk8I456aG +cUxYVAH6x/sET1I+79LJJ9bh7Exj4THlohMQPvPAxAghg5d+Ii8iD3cS6mZO5C8e +4aE8vgCGtzLJoAuEcriPqg== +-----END PRIVATE KEY-----