fixes and secure storage
This commit is contained in:
parent
c287d77cf8
commit
1bfdd73389
21 changed files with 75079 additions and 68225 deletions
|
|
@ -202,6 +202,17 @@ jobs:
|
||||||
systemctl status mnemo_cards_server --no-pager
|
systemctl status mnemo_cards_server --no-pager
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
|
- name: Generate and Deploy Nginx Configs
|
||||||
|
run: |
|
||||||
|
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
||||||
|
set -e
|
||||||
|
echo "🔧 Generating and deploying nginx configurations..."
|
||||||
|
cd ~/tools/deploy
|
||||||
|
./generate-nginx-configs.sh
|
||||||
|
./deploy-nginx-configs.sh
|
||||||
|
./check-nginx.sh
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
- name: Ensure Nginx Running
|
- name: Ensure Nginx Running
|
||||||
run: |
|
run: |
|
||||||
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1c4dc119e18bcf1ad36e5635fba58ce0
|
cbc289e61044aa6e6f63e7abe894d47e
|
||||||
|
|
@ -1 +1 @@
|
||||||
1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf
asset1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf
|
1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf
asset1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf
icons/ad.webp
asset
icons/ad.webpicons/back.webp
asseticons/back.webpicons/cards.webp
asseticons/cards.webpicons/chat.webp
asseticons/chat.webpicons/clock.webp
asseticons/clock.webpicons/crown.webp
asseticons/crown.webpicons/down.webp
asseticons/down.webpicons/download.webp
asseticons/download.webpicons/exit.webp
asseticons/exit.webpicons/exit2.webp
asseticons/exit2.webpicons/exit3.webp
asseticons/exit3.webpicons/gift.webp
asseticons/gift.webpicons/google.webp
asseticons/google.webpicons/heart.webp
asseticons/heart.webpicons/heart_fill.webp
asset1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf
asset1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttfasset1../mnemo_cards/fonts/Nunito-VariableFont_wght.ttfasseticons/mic_off.webpicons/mic_on.webp
asseticons/mic_on.webpicons/next.webp
asseticons/next.webpicons/profile.webp
asseticons/profile.webpicons/settings.webp
asseticons/settings.webpicons/shuffle.webp
asseticons/shuffle.webpicons/skull.webp
asseticons/skull.webpicons/small_circle.webp
asseticons/small_circle.webpicons/sound_off.webp
asseticons/sound_off.webpicons/sound_on.webp
asseticons/sound_on.webpicons/telegram.webp
asseticons/telegram.webp
icons/tg.webp
asset
icons/tg.webpicons/view.webp
asseticons/view.webp2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf
|
||||||
|
|
@ -1 +1 @@
|
||||||
"DQIHMS4uL21uZW1vX2NhcmRzL2ZvbnRzL051bml0by1WYXJpYWJsZUZvbnRfd2dodC50dGYMAQ0BBwVhc3NldAcxLi4vbW5lbW9fY2FyZHMvZm9udHMvTnVuaXRvLVZhcmlhYmxlRm9udF93Z2h0LnR0ZgcycGFja2FnZXMvY3VwZXJ0aW5vX2ljb25zL2Fzc2V0cy9DdXBlcnRpbm9JY29ucy50dGYMAQ0BBwVhc3NldAcycGFja2FnZXMvY3VwZXJ0aW5vX2ljb25zL2Fzc2V0cy9DdXBlcnRpbm9JY29ucy50dGY="
|
"DR8HMS4uL21uZW1vX2NhcmRzL2ZvbnRzL051bml0by1WYXJpYWJsZUZvbnRfd2dodC50dGYMAQ0BBwVhc3NldAcxLi4vbW5lbW9fY2FyZHMvZm9udHMvTnVuaXRvLVZhcmlhYmxlRm9udF93Z2h0LnR0ZgcNaWNvbnMvYWQud2VicAwBDQEHBWFzc2V0Bw1pY29ucy9hZC53ZWJwBw9pY29ucy9iYWNrLndlYnAMAQ0BBwVhc3NldAcPaWNvbnMvYmFjay53ZWJwBxBpY29ucy9jYXJkcy53ZWJwDAENAQcFYXNzZXQHEGljb25zL2NhcmRzLndlYnAHD2ljb25zL2NoYXQud2VicAwBDQEHBWFzc2V0Bw9pY29ucy9jaGF0LndlYnAHEGljb25zL2Nsb2NrLndlYnAMAQ0BBwVhc3NldAcQaWNvbnMvY2xvY2sud2VicAcQaWNvbnMvY3Jvd24ud2VicAwBDQEHBWFzc2V0BxBpY29ucy9jcm93bi53ZWJwBw9pY29ucy9kb3duLndlYnAMAQ0BBwVhc3NldAcPaWNvbnMvZG93bi53ZWJwBxNpY29ucy9kb3dubG9hZC53ZWJwDAENAQcFYXNzZXQHE2ljb25zL2Rvd25sb2FkLndlYnAHD2ljb25zL2V4aXQud2VicAwBDQEHBWFzc2V0Bw9pY29ucy9leGl0LndlYnAHEGljb25zL2V4aXQyLndlYnAMAQ0BBwVhc3NldAcQaWNvbnMvZXhpdDIud2VicAcQaWNvbnMvZXhpdDMud2VicAwBDQEHBWFzc2V0BxBpY29ucy9leGl0My53ZWJwBw9pY29ucy9naWZ0LndlYnAMAQ0BBwVhc3NldAcPaWNvbnMvZ2lmdC53ZWJwBxFpY29ucy9nb29nbGUud2VicAwBDQEHBWFzc2V0BxFpY29ucy9nb29nbGUud2VicAcQaWNvbnMvaGVhcnQud2VicAwBDQEHBWFzc2V0BxBpY29ucy9oZWFydC53ZWJwBxVpY29ucy9oZWFydF9maWxsLndlYnAMAQ0BBwVhc3NldAcVaWNvbnMvaGVhcnRfZmlsbC53ZWJwBw9pY29ucy9sb2NrLndlYnAMAQ0BBwVhc3NldAcPaWNvbnMvbG9jay53ZWJwBxJpY29ucy9taWNfb2ZmLndlYnAMAQ0BBwVhc3NldAcSaWNvbnMvbWljX29mZi53ZWJwBxFpY29ucy9taWNfb24ud2VicAwBDQEHBWFzc2V0BxFpY29ucy9taWNfb24ud2VicAcPaWNvbnMvbmV4dC53ZWJwDAENAQcFYXNzZXQHD2ljb25zL25leHQud2VicAcSaWNvbnMvcHJvZmlsZS53ZWJwDAENAQcFYXNzZXQHEmljb25zL3Byb2ZpbGUud2VicAcTaWNvbnMvc2V0dGluZ3Mud2VicAwBDQEHBWFzc2V0BxNpY29ucy9zZXR0aW5ncy53ZWJwBxJpY29ucy9zaHVmZmxlLndlYnAMAQ0BBwVhc3NldAcSaWNvbnMvc2h1ZmZsZS53ZWJwBxBpY29ucy9za3VsbC53ZWJwDAENAQcFYXNzZXQHEGljb25zL3NrdWxsLndlYnAHF2ljb25zL3NtYWxsX2NpcmNsZS53ZWJwDAENAQcFYXNzZXQHF2ljb25zL3NtYWxsX2NpcmNsZS53ZWJwBxRpY29ucy9zb3VuZF9vZmYud2VicAwBDQEHBWFzc2V0BxRpY29ucy9zb3VuZF9vZmYud2VicAcTaWNvbnMvc291bmRfb24ud2VicAwBDQEHBWFzc2V0BxNpY29ucy9zb3VuZF9vbi53ZWJwBxNpY29ucy90ZWxlZ3JhbS53ZWJwDAENAQcFYXNzZXQHE2ljb25zL3RlbGVncmFtLndlYnAHDWljb25zL3RnLndlYnAMAQ0BBwVhc3NldAcNaWNvbnMvdGcud2VicAcPaWNvbnMvdmlldy53ZWJwDAENAQcFYXNzZXQHD2ljb25zL3ZpZXcud2VicAcycGFja2FnZXMvY3VwZXJ0aW5vX2ljb25zL2Fzc2V0cy9DdXBlcnRpbm9JY29ucy50dGYMAQ0BBwVhc3NldAcycGFja2FnZXMvY3VwZXJ0aW5vX2ljb25zL2Fzc2V0cy9DdXBlcnRpbm9JY29ucy50dGY="
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf":["../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
|
{"../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf":["../mnemo_cards/fonts/Nunito-VariableFont_wght.ttf"],"icons/ad.webp":["icons/ad.webp"],"icons/back.webp":["icons/back.webp"],"icons/cards.webp":["icons/cards.webp"],"icons/chat.webp":["icons/chat.webp"],"icons/clock.webp":["icons/clock.webp"],"icons/crown.webp":["icons/crown.webp"],"icons/down.webp":["icons/down.webp"],"icons/download.webp":["icons/download.webp"],"icons/exit.webp":["icons/exit.webp"],"icons/exit2.webp":["icons/exit2.webp"],"icons/exit3.webp":["icons/exit3.webp"],"icons/gift.webp":["icons/gift.webp"],"icons/google.webp":["icons/google.webp"],"icons/heart.webp":["icons/heart.webp"],"icons/heart_fill.webp":["icons/heart_fill.webp"],"icons/lock.webp":["icons/lock.webp"],"icons/mic_off.webp":["icons/mic_off.webp"],"icons/mic_on.webp":["icons/mic_on.webp"],"icons/next.webp":["icons/next.webp"],"icons/profile.webp":["icons/profile.webp"],"icons/settings.webp":["icons/settings.webp"],"icons/shuffle.webp":["icons/shuffle.webp"],"icons/skull.webp":["icons/skull.webp"],"icons/small_circle.webp":["icons/small_circle.webp"],"icons/sound_off.webp":["icons/sound_off.webp"],"icons/sound_on.webp":["icons/sound_on.webp"],"icons/telegram.webp":["icons/telegram.webp"],"icons/tg.webp":["icons/tg.webp"],"icons/view.webp":["icons/view.webp"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
|
||||||
Binary file not shown.
|
|
@ -38,6 +38,6 @@ _flutter.buildConfig = {"engineRevision":"d3d45dcf251823c1769909cd43698d126db38d
|
||||||
|
|
||||||
_flutter.loader.load({
|
_flutter.loader.load({
|
||||||
serviceWorkerSettings: {
|
serviceWorkerSettings: {
|
||||||
serviceWorkerVersion: "2237867940"
|
serviceWorkerVersion: "1664190830"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
|
||||||
const TEMP = 'flutter-temp-cache';
|
const TEMP = 'flutter-temp-cache';
|
||||||
const CACHE_NAME = 'flutter-app-cache';
|
const CACHE_NAME = 'flutter-app-cache';
|
||||||
|
|
||||||
const RESOURCES = {"flutter_bootstrap.js": "7833490e08899f1a73e0d1a28dce5806",
|
const RESOURCES = {"flutter_bootstrap.js": "1016c5edf68382e5cd6bc30dc8abc968",
|
||||||
"version.json": "28542ad255b8c0abed0b83ec843a2417",
|
"version.json": "28542ad255b8c0abed0b83ec843a2417",
|
||||||
"index.html": "2414db4ab7b157a70906335536c9b12f",
|
"index.html": "bea65743d155de5b43dd38c2a02fa14d",
|
||||||
"/": "2414db4ab7b157a70906335536c9b12f",
|
"/": "bea65743d155de5b43dd38c2a02fa14d",
|
||||||
"main.dart.js": "3fb19ec457a2d8c0efd8fa87eaed0804",
|
"main.dart.js": "efd61556cfb88ace9d0e42213140da3c",
|
||||||
"flutter.js": "888483df48293866f9f41d3d9274a779",
|
"flutter.js": "888483df48293866f9f41d3d9274a779",
|
||||||
"mnemo_cards/fonts/Nunito-VariableFont_wght.ttf": "ea0ad4c72a135f9a43ec7bb83f2469aa",
|
"mnemo_cards/fonts/Nunito-VariableFont_wght.ttf": "ea0ad4c72a135f9a43ec7bb83f2469aa",
|
||||||
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
|
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
|
||||||
|
|
@ -16,15 +16,44 @@ const RESOURCES = {"flutter_bootstrap.js": "7833490e08899f1a73e0d1a28dce5806",
|
||||||
"icons/Icon-maskable-512.png": "301a7604d45b3e739efc881eb04896ea",
|
"icons/Icon-maskable-512.png": "301a7604d45b3e739efc881eb04896ea",
|
||||||
"icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1",
|
"icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1",
|
||||||
"manifest.json": "52ae309b087ade76dc53b15e820872a5",
|
"manifest.json": "52ae309b087ade76dc53b15e820872a5",
|
||||||
"foos.js": "da94bf5c2c30afde57065bf69154070a",
|
"foos.js": "15c33cb4bb47bf3dbeae9bbe5c330796",
|
||||||
"assets/AssetManifest.json": "d858d53ad6fe5329b2552f4f1c8ef480",
|
"assets/AssetManifest.json": "4446605ce656b304ed309216b1cb0766",
|
||||||
"assets/NOTICES": "9a4cb06d9c96803dbf84a97820925f74",
|
"assets/NOTICES": "9a4cb06d9c96803dbf84a97820925f74",
|
||||||
"assets/FontManifest.json": "39e62425377b8c56565d232f537294b4",
|
"assets/FontManifest.json": "39e62425377b8c56565d232f537294b4",
|
||||||
"assets/AssetManifest.bin.json": "7493ed26bdf665567c349d7c0c2862b1",
|
"assets/AssetManifest.bin.json": "75e03a20d827286422d0de35a65b7ff1",
|
||||||
|
"assets/icons/google.webp": "9481bad94ab5aec99bdecac8faa569bd",
|
||||||
|
"assets/icons/sound_on.webp": "ab2e4d5e335c7ab92eb6513f1196df7e",
|
||||||
|
"assets/icons/profile.webp": "9a9e7ad8b4f2303e9d5f92c0129724af",
|
||||||
|
"assets/icons/shuffle.webp": "cde1214b225c40111f69392d15817c31",
|
||||||
|
"assets/icons/heart_fill.webp": "b6e8d7faa8975d9eb682db95eeaf9eb0",
|
||||||
|
"assets/icons/mic_off.webp": "d5dc7d727187c8a8a23040687398366e",
|
||||||
|
"assets/icons/heart.webp": "f6c6182054002a5e38e9f4dc001240ba",
|
||||||
|
"assets/icons/telegram.webp": "709dc006e25be6b47163d64ae0b9f237",
|
||||||
|
"assets/icons/skull.webp": "b17661c79a540f5f86594c619b2d3b7a",
|
||||||
|
"assets/icons/back.webp": "8f20891568ae5a93b84e9c3d6beccbe7",
|
||||||
|
"assets/icons/cards.webp": "4d8b07569e721a06174d28dabf480514",
|
||||||
|
"assets/icons/small_circle.webp": "77c43c50bc56e2476ec6beec1776ce3b",
|
||||||
|
"assets/icons/crown.webp": "935ac28b3a9ea73c60048c515c8794b7",
|
||||||
|
"assets/icons/download.webp": "7848632925770aa35bbd74839f5fc14a",
|
||||||
|
"assets/icons/mic_on.webp": "ac59064c2351867e8cba3e56ecaa08f1",
|
||||||
|
"assets/icons/view.webp": "004ff539554b79f3be0d828b8d6eb518",
|
||||||
|
"assets/icons/next.webp": "7b954a801178618698e3783669e7c581",
|
||||||
|
"assets/icons/gift.webp": "f29ebf5e3aea9051a18049a5b0372e45",
|
||||||
|
"assets/icons/exit2.webp": "38d5c1c37d68072845c0070b83a15687",
|
||||||
|
"assets/icons/settings.webp": "497c5270161d0c259c40f3db24a23e49",
|
||||||
|
"assets/icons/lock.webp": "b4258a96d1d601718fb3a0895bcf831e",
|
||||||
|
"assets/icons/sound_off.webp": "9f94cbccc36e6a066b78332f61cb2a1b",
|
||||||
|
"assets/icons/tg.webp": "b244a357bdb75e0978f42e8f44801304",
|
||||||
|
"assets/icons/chat.webp": "31375fca81fa9fc16cb98ae3b1c7b608",
|
||||||
|
"assets/icons/exit.webp": "23851a717f974d8869ca7286cf603198",
|
||||||
|
"assets/icons/ad.webp": "c18fcd1ca174d305a663122274e77541",
|
||||||
|
"assets/icons/clock.webp": "3f56d2f02c97218b436f09b0114745b2",
|
||||||
|
"assets/icons/exit3.webp": "93390eac54377fe84f8e72cd1ba9c86f",
|
||||||
|
"assets/icons/down.webp": "a03694c11d0c594c407cfd07a917e6ea",
|
||||||
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "3c81d572636c9fdf59d16a1b2a926270",
|
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "3c81d572636c9fdf59d16a1b2a926270",
|
||||||
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
|
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
|
||||||
"assets/AssetManifest.bin": "fb1b522630fd39c059eeec2f4cfa89da",
|
"assets/AssetManifest.bin": "999738b9fec34c457d537edf879cbd21",
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "8419d0bcce9edacabc13177aa440e80e",
|
"assets/fonts/MaterialIcons-Regular.otf": "f88dfb9ff0e5a2bc4e1872513ff14262",
|
||||||
"canvaskit/skwasm.js": "1ef3ea3a0fec4569e5d531da25f34095",
|
"canvaskit/skwasm.js": "1ef3ea3a0fec4569e5d531da25f34095",
|
||||||
"canvaskit/skwasm_heavy.js": "413f5b2b2d9345f37de148e2544f584f",
|
"canvaskit/skwasm_heavy.js": "413f5b2b2d9345f37de148e2544f584f",
|
||||||
"canvaskit/skwasm.js.symbols": "0088242d10d7e7d6d2649d1fe1bda7c1",
|
"canvaskit/skwasm.js.symbols": "0088242d10d7e7d6d2649d1fe1bda7c1",
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,235 @@
|
||||||
// Initialize Adsgram with the configured block ID
|
// Adsgram SDK integration for rewarded ads
|
||||||
const AdController = window.Adsgram.init({ blockId: "16505" });
|
// This file provides a bridge between Dart code and the Adsgram JavaScript SDK
|
||||||
|
|
||||||
// Store reward callback function
|
// Wait for SDK to load if it's not immediately available
|
||||||
|
(function() {
|
||||||
|
let sdkCheckAttempts = 0;
|
||||||
|
const maxCheckAttempts = 50; // Check for up to 5 seconds (50 * 100ms)
|
||||||
|
|
||||||
|
function checkSDK() {
|
||||||
|
if (typeof window.Adsgram !== 'undefined') {
|
||||||
|
console.log('Adsgram SDK loaded successfully');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdkCheckAttempts++;
|
||||||
|
if (sdkCheckAttempts < maxCheckAttempts) {
|
||||||
|
setTimeout(checkSDK, 100);
|
||||||
|
} else {
|
||||||
|
console.warn('Adsgram SDK not loaded after timeout. Make sure sad.min.js is included in index.html');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start checking after a short delay to allow script to load
|
||||||
|
setTimeout(checkSDK, 100);
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Store callbacks for ad lifecycle events
|
||||||
let rewardCallback = null;
|
let rewardCallback = null;
|
||||||
let errorCallback = null;
|
let errorCallback = null;
|
||||||
|
let currentAdController = null;
|
||||||
|
|
||||||
// Function to show ad (called from Dart)
|
// Default block ID (can be overridden)
|
||||||
|
const DEFAULT_BLOCK_ID = "16505";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Adsgram ad controller with a specific block ID
|
||||||
|
* @param {string} blockId - The Adsgram block ID
|
||||||
|
* @returns {object} Adsgram ad controller instance
|
||||||
|
* @throws {Error} If SDK is not available or initialization fails
|
||||||
|
*/
|
||||||
|
function initAdController(blockId) {
|
||||||
|
if (typeof window.Adsgram === 'undefined') {
|
||||||
|
const error = 'Adsgram SDK not available. Make sure sad.min.js is loaded.';
|
||||||
|
console.error(error);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blockId || typeof blockId !== 'string' || blockId.trim() === '') {
|
||||||
|
const error = 'Invalid block ID provided';
|
||||||
|
console.error(error);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const controller = window.Adsgram.init({ blockId: blockId });
|
||||||
|
if (!controller) {
|
||||||
|
throw new Error('Failed to initialize Adsgram controller: init returned null');
|
||||||
|
}
|
||||||
|
return controller;
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error?.message || error?.toString() || 'Unknown initialization error';
|
||||||
|
console.error('Failed to initialize Adsgram controller:', errorMessage);
|
||||||
|
throw new Error(`Failed to initialize Adsgram controller: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a rewarded ad using the default block ID
|
||||||
|
* Called from Dart code via js_util.callMethod
|
||||||
|
* @returns {Promise} Promise that resolves when ad completes or rejects on error
|
||||||
|
*/
|
||||||
function showAd() {
|
function showAd() {
|
||||||
return AdController.show().then((result) => {
|
return showAdWithBlockId(DEFAULT_BLOCK_ID);
|
||||||
// user watch ad till the end or close it in interstitial format
|
|
||||||
// your code to reward user for rewarded format
|
|
||||||
console.log('Ad completed successfully', result);
|
|
||||||
|
|
||||||
// Call reward callback if set
|
|
||||||
if (window.rewardCallback && typeof window.rewardCallback === 'function') {
|
|
||||||
window.rewardCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}).catch((result) => {
|
|
||||||
// user get error during playing ad
|
|
||||||
// do nothing or whatever you want
|
|
||||||
console.error('Ad failed', result);
|
|
||||||
|
|
||||||
// Call error callback if set
|
|
||||||
if (window.errorCallback && typeof window.errorCallback === 'function') {
|
|
||||||
window.errorCallback(JSON.stringify(result, null, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to show ad with specific block ID
|
/**
|
||||||
|
* Show a rewarded ad with a specific block ID
|
||||||
|
* Called from Dart code via js_util.callMethod
|
||||||
|
* @param {string} blockId - The Adsgram block ID to use
|
||||||
|
* @returns {Promise} Promise that resolves when ad completes or rejects on error
|
||||||
|
*/
|
||||||
function showAdWithBlockId(blockId) {
|
function showAdWithBlockId(blockId) {
|
||||||
const dynamicController = window.Adsgram.init({ blockId: blockId });
|
// Validate block ID
|
||||||
return dynamicController.show().then((result) => {
|
if (!blockId || typeof blockId !== 'string' || blockId.trim() === '') {
|
||||||
console.log('Ad completed successfully for block', blockId, result);
|
const error = 'Invalid block ID provided';
|
||||||
|
console.error(error);
|
||||||
|
if (errorCallback && typeof errorCallback === 'function') {
|
||||||
|
try {
|
||||||
|
errorCallback(error);
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in error callback:', callbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(error));
|
||||||
|
}
|
||||||
|
|
||||||
// Call reward callback if set
|
// Check SDK availability
|
||||||
if (window.rewardCallback && typeof window.rewardCallback === 'function') {
|
if (typeof window.Adsgram === 'undefined') {
|
||||||
window.rewardCallback();
|
const error = 'Adsgram SDK not available. Make sure sad.min.js is loaded.';
|
||||||
|
console.error(error);
|
||||||
|
if (errorCallback && typeof errorCallback === 'function') {
|
||||||
|
try {
|
||||||
|
errorCallback(error);
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in error callback:', callbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize controller for this specific block
|
||||||
|
currentAdController = initAdController(blockId);
|
||||||
|
|
||||||
|
if (!currentAdController || typeof currentAdController.show !== 'function') {
|
||||||
|
const error = 'Invalid ad controller: show method not available';
|
||||||
|
console.error(error);
|
||||||
|
if (errorCallback && typeof errorCallback === 'function') {
|
||||||
|
try {
|
||||||
|
errorCallback(error);
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in error callback:', callbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
// Show the ad
|
||||||
}).catch((result) => {
|
return currentAdController.show().then((result) => {
|
||||||
console.error('Ad failed for block', blockId, result);
|
// Ad completed successfully - user watched till the end
|
||||||
|
console.log('Ad completed successfully', result);
|
||||||
|
|
||||||
// Call error callback if set
|
// Call reward callback if set
|
||||||
if (window.errorCallback && typeof window.errorCallback === 'function') {
|
if (rewardCallback && typeof rewardCallback === 'function') {
|
||||||
window.errorCallback(JSON.stringify(result, null, 4));
|
try {
|
||||||
|
rewardCallback();
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in reward callback:', callbackError);
|
||||||
|
// Don't fail the promise if callback has an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}).catch((error) => {
|
||||||
|
// Ad failed or was closed early
|
||||||
|
console.error('Ad failed or was closed:', error);
|
||||||
|
|
||||||
|
// Format error message
|
||||||
|
let errorMessage = 'Ad failed';
|
||||||
|
if (error) {
|
||||||
|
if (typeof error === 'object') {
|
||||||
|
if (error.message) {
|
||||||
|
errorMessage = error.message;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
errorMessage = JSON.stringify(error);
|
||||||
|
} catch (e) {
|
||||||
|
errorMessage = error.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorMessage = error.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call error callback if set
|
||||||
|
if (errorCallback && typeof errorCallback === 'function') {
|
||||||
|
try {
|
||||||
|
errorCallback(errorMessage);
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in error callback:', callbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Initialization or show() call failed
|
||||||
|
let errorMessage = 'Failed to show ad';
|
||||||
|
if (error) {
|
||||||
|
if (error.message) {
|
||||||
|
errorMessage = error.message;
|
||||||
|
} else {
|
||||||
|
errorMessage = error.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.error('Failed to show ad:', errorMessage);
|
||||||
|
|
||||||
|
if (errorCallback && typeof errorCallback === 'function') {
|
||||||
|
try {
|
||||||
|
errorCallback(errorMessage);
|
||||||
|
} catch (callbackError) {
|
||||||
|
console.error('Error in error callback:', callbackError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw result;
|
return Promise.reject(error);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to set reward callback from Dart
|
/**
|
||||||
|
* Set the reward callback function
|
||||||
|
* Called from Dart code to register callback for successful ad completion
|
||||||
|
* @param {Function} callback - Function to call when ad completes successfully
|
||||||
|
*/
|
||||||
function setRewardCallback(callback) {
|
function setRewardCallback(callback) {
|
||||||
window.rewardCallback = callback;
|
if (callback && typeof callback === 'function') {
|
||||||
|
rewardCallback = callback;
|
||||||
|
console.log('Reward callback registered');
|
||||||
|
} else {
|
||||||
|
console.warn('Invalid reward callback provided');
|
||||||
|
rewardCallback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to set error callback from Dart
|
/**
|
||||||
|
* Set the error callback function
|
||||||
|
* Called from Dart code to register callback for ad errors
|
||||||
|
* @param {Function} callback - Function to call when ad fails (takes error message as parameter)
|
||||||
|
*/
|
||||||
function setErrorCallback(callback) {
|
function setErrorCallback(callback) {
|
||||||
window.errorCallback = callback;
|
if (callback && typeof callback === 'function') {
|
||||||
|
errorCallback = callback;
|
||||||
|
console.log('Error callback registered');
|
||||||
|
} else {
|
||||||
|
console.warn('Invalid error callback provided');
|
||||||
|
errorCallback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make functions available globally for Dart interop
|
||||||
|
window.showAd = showAd;
|
||||||
|
window.showAdWithBlockId = showAdWithBlockId;
|
||||||
|
window.setRewardCallback = setRewardCallback;
|
||||||
|
window.setErrorCallback = setErrorCallback;
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
import 'package:yx_scope/yx_scope.dart';
|
import 'package:yx_scope/yx_scope.dart';
|
||||||
|
|
||||||
import '../../../domain/services/http_repository_v2.dart';
|
import '../../../domain/services/http_repository_v2.dart';
|
||||||
|
|
@ -11,13 +10,6 @@ import '../app_scope_container.dart';
|
||||||
class StorageModule extends ScopeModule<AppScopeContainer> {
|
class StorageModule extends ScopeModule<AppScopeContainer> {
|
||||||
StorageModule(super.container);
|
StorageModule(super.container);
|
||||||
|
|
||||||
// SecureStorage for tokens (legacy, kept for compatibility)
|
|
||||||
late final secureStorageDep = dep(
|
|
||||||
() => const FlutterSecureStorage(
|
|
||||||
aOptions: AndroidOptions(encryptedSharedPreferences: true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// HTTP Repository V2 (primary - for web app)
|
// HTTP Repository V2 (primary - for web app)
|
||||||
late final httpRepositoryV2Dep = dep(
|
late final httpRepositoryV2Dep = dep(
|
||||||
() => HttpRepositoryV2.withDefaults(container.sharedPreferences),
|
() => HttpRepositoryV2.withDefaults(container.sharedPreferences),
|
||||||
|
|
@ -28,8 +20,6 @@ class StorageModule extends ScopeModule<AppScopeContainer> {
|
||||||
() => ThemeStateManager(container.sharedPreferences),
|
() => ThemeStateManager(container.sharedPreferences),
|
||||||
);
|
);
|
||||||
|
|
||||||
FlutterSecureStorage get secureStorage => secureStorageDep.get;
|
|
||||||
|
|
||||||
/// Primary HTTP repository - uses API v2
|
/// Primary HTTP repository - uses API v2
|
||||||
HttpRepositoryV2 get httpRepository => httpRepositoryV2Dep.get;
|
HttpRepositoryV2 get httpRepository => httpRepositoryV2Dep.get;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.9.3"
|
version: "5.9.3"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ dependencies:
|
||||||
|
|
||||||
# Storage
|
# Storage
|
||||||
shared_preferences: ^2.2.3
|
shared_preferences: ^2.2.3
|
||||||
flutter_secure_storage: ^9.2.2
|
|
||||||
|
|
||||||
# UI
|
# UI
|
||||||
flutter_screenutil: ^5.9.0
|
flutter_screenutil: ^5.9.0
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,16 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Deploy updated nginx configurations for all services
|
||||||
|
echo "🔧 Deploying updated nginx configurations..."
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./generate-nginx-configs.sh
|
||||||
|
./deploy-nginx-configs.sh
|
||||||
|
|
||||||
|
# Final nginx check
|
||||||
|
echo "🔍 Final nginx status check..."
|
||||||
|
./check-nginx.sh
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl start mnemo_cards_server
|
sudo systemctl start mnemo_cards_server
|
||||||
journalctl -u mnemo_cards_server --since "1min ago"
|
journalctl -u mnemo_cards_server --since "1min ago"
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Script to check and reload nginx
|
# Script to check and fix nginx configuration and service
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SERVER_IP="147.45.152.129"
|
SERVER_IP="147.45.152.129"
|
||||||
SERVER_USER="root"
|
SERVER_USER="root"
|
||||||
|
|
||||||
echo "🔧 Checking and reloading nginx..."
|
echo "🔧 Checking and fixing nginx..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "📊 Checking nginx status..."
|
echo "📊 Checking nginx installation..."
|
||||||
if /usr/sbin/nginx -v 2>&1; then
|
if /usr/sbin/nginx -v 2>&1; then
|
||||||
echo "✅ nginx is installed"
|
echo "✅ nginx is installed"
|
||||||
else
|
else
|
||||||
|
|
@ -21,60 +21,166 @@ ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🧹 Checking for port conflicts..."
|
||||||
|
|
||||||
|
# Check if ports 80 and 443 are free
|
||||||
|
if ss -tlnp | grep -q ":80 "; then
|
||||||
|
echo "⚠️ Port 80 is already in use:"
|
||||||
|
ss -tlnp | grep ":80 "
|
||||||
|
echo "Attempting to free port 80..."
|
||||||
|
# Kill processes listening on port 80 (except nginx)
|
||||||
|
ss -tlnp | grep ":80 " | grep -v nginx | awk '{print $6}' | cut -d'=' -f2 | cut -d',' -f1 | xargs -r kill -9 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ss -tlnp | grep -q ":443 "; then
|
||||||
|
echo "⚠️ Port 443 is already in use:"
|
||||||
|
ss -tlnp | grep ":443 "
|
||||||
|
echo "Attempting to free port 443..."
|
||||||
|
# Kill processes listening on port 443 (except nginx)
|
||||||
|
ss -tlnp | grep ":443 " | grep -v nginx | awk '{print $6}' | cut -d'=' -f2 | cut -d',' -f1 | xargs -r kill -9 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🧹 Checking for orphaned nginx processes..."
|
||||||
|
NGINX_PIDS=$(pgrep -f nginx | wc -l)
|
||||||
|
if [ "$NGINX_PIDS" -gt 0 ]; then
|
||||||
|
echo "⚠️ Found $NGINX_PIDS nginx processes running"
|
||||||
|
if ! systemctl is-active --quiet nginx; then
|
||||||
|
echo "Systemd thinks nginx is stopped, but processes exist. Cleaning up..."
|
||||||
|
pkill -9 nginx
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 Testing nginx configuration..."
|
echo "📊 Testing nginx configuration..."
|
||||||
/usr/sbin/nginx -t
|
if /usr/sbin/nginx -t; then
|
||||||
|
echo "✅ Configuration syntax is valid"
|
||||||
|
else
|
||||||
|
echo "❌ Configuration syntax error!"
|
||||||
|
echo "Checking for common issues..."
|
||||||
|
|
||||||
|
# Check for missing events block
|
||||||
|
if ! grep -q "events {" /etc/nginx/nginx.conf; then
|
||||||
|
echo "⚠️ Missing events block in nginx.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for server blocks outside http
|
||||||
|
if grep -q "^server {" /etc/nginx/nginx.conf; then
|
||||||
|
echo "⚠️ Found server block outside http context in nginx.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for duplicate directives
|
||||||
|
DUPLICATE_USER=$(grep "^user " /etc/nginx/nginx.conf | wc -l)
|
||||||
|
if [ "$DUPLICATE_USER" -gt 1 ]; then
|
||||||
|
echo "⚠️ Found $DUPLICATE_USER 'user' directives (should be 1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Please fix the configuration errors and try again"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 Checking nginx service status..."
|
echo "📊 Checking nginx service status..."
|
||||||
systemctl status nginx --no-pager || true
|
if systemctl is-active --quiet nginx; then
|
||||||
|
echo "✅ nginx service is running"
|
||||||
|
systemctl status nginx --no-pager | head -5
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔄 Reloading nginx..."
|
echo "🔄 Reloading nginx configuration..."
|
||||||
systemctl reload nginx
|
if systemctl reload nginx; then
|
||||||
|
echo "✅ nginx reloaded successfully"
|
||||||
echo "✅ nginx reloaded"
|
else
|
||||||
|
echo "❌ nginx reload failed, restarting..."
|
||||||
echo ""
|
systemctl restart nginx
|
||||||
echo "📊 Checking if nginx is running..."
|
fi
|
||||||
systemctl is-active nginx && echo "✅ nginx is active" || echo "❌ nginx is not active"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Checking vscode.mnemo-cards.online nginx config..."
|
|
||||||
if [ -f /etc/nginx/sites-enabled/vscode.mnemo-cards.online ]; then
|
|
||||||
echo "✅ vscode nginx config is enabled"
|
|
||||||
elif [ -f /etc/nginx/sites-available/vscode.mnemo-cards.online ]; then
|
|
||||||
echo "⚠️ vscode nginx config exists but not enabled"
|
|
||||||
echo "Enabling it..."
|
|
||||||
ln -sf /etc/nginx/sites-available/vscode.mnemo-cards.online /etc/nginx/sites-enabled/
|
|
||||||
/usr/sbin/nginx -t && systemctl reload nginx
|
|
||||||
echo "✅ Enabled and reloaded"
|
|
||||||
else
|
else
|
||||||
echo "❌ vscode nginx config not found"
|
echo "⚠️ nginx service is not running, starting..."
|
||||||
|
if systemctl start nginx; then
|
||||||
|
echo "✅ nginx started successfully"
|
||||||
|
else
|
||||||
|
echo "❌ nginx failed to start!"
|
||||||
|
systemctl status nginx --no-pager
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 Checking code.mnemo-cards.online DNS resolution..."
|
echo "📊 Checking if nginx is active..."
|
||||||
if host code.mnemo-cards.online &> /dev/null; then
|
if systemctl is-active --quiet nginx; then
|
||||||
host code.mnemo-cards.online
|
echo "✅ nginx is active"
|
||||||
else
|
else
|
||||||
echo "⚠️ DNS resolution failed for code.mnemo-cards.online"
|
echo "❌ nginx is not active"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if host vscode.mnemo-cards.online &> /dev/null; then
|
echo ""
|
||||||
host vscode.mnemo-cards.online
|
echo "📊 Checking site configurations..."
|
||||||
|
|
||||||
|
# Check all expected configurations
|
||||||
|
SITES=("vscode.mnemo-cards.online" "code.mnemo-cards.online" "mnemo-cards.online")
|
||||||
|
for site in "${SITES[@]}"; do
|
||||||
|
if [ -f "/etc/nginx/sites-enabled/$site" ]; then
|
||||||
|
echo "✅ $site config is enabled"
|
||||||
|
elif [ -f "/etc/nginx/sites-available/$site" ]; then
|
||||||
|
echo "⚠️ $site config exists but not enabled"
|
||||||
|
echo "Enabling $site..."
|
||||||
|
ln -sf "/etc/nginx/sites-available/$site" "/etc/nginx/sites-enabled/"
|
||||||
|
/usr/sbin/nginx -t && systemctl reload nginx
|
||||||
|
echo "✅ $site enabled and reloaded"
|
||||||
|
else
|
||||||
|
echo "❌ $site config not found"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Checking SSL certificates..."
|
||||||
|
if [ -d "/etc/letsencrypt/live/mnemo-cards.online" ]; then
|
||||||
|
echo "✅ Let's Encrypt certificates found for mnemo-cards.online"
|
||||||
|
# Ensure correct permissions
|
||||||
|
chmod 755 /etc/letsencrypt/archive 2>/dev/null || true
|
||||||
|
chmod 755 /etc/letsencrypt/live 2>/dev/null || true
|
||||||
|
find /etc/letsencrypt -type d -exec chmod 755 {} \; 2>/dev/null || true
|
||||||
|
find /etc/letsencrypt -type f -exec chmod 644 {} \; 2>/dev/null || true
|
||||||
|
chmod 600 /etc/letsencrypt/archive/mnemo-cards.online/privkey*.pem 2>/dev/null || true
|
||||||
|
chmod 600 /etc/letsencrypt/live/mnemo-cards.online/privkey.pem 2>/dev/null || true
|
||||||
else
|
else
|
||||||
echo "⚠️ DNS resolution failed for vscode.mnemo-cards.online"
|
echo "⚠️ Let's Encrypt certificates not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Checking DNS resolution..."
|
||||||
|
DOMAINS=("code.mnemo-cards.online" "vscode.mnemo-cards.online" "mnemo-cards.online")
|
||||||
|
for domain in "${DOMAINS[@]}"; do
|
||||||
|
if host "$domain" &> /dev/null; then
|
||||||
|
echo "✅ $domain resolves correctly"
|
||||||
|
else
|
||||||
|
echo "⚠️ DNS resolution failed for $domain"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Testing HTTP responses..."
|
||||||
|
for domain in "${DOMAINS[@]}"; do
|
||||||
|
if curl -I -k "https://$domain/" --max-time 10 --silent | head -1 | grep -q "200\|301\|302"; then
|
||||||
|
echo "✅ $domain responds correctly"
|
||||||
|
else
|
||||||
|
echo "⚠️ $domain not responding or returning error"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "✅ Done!"
|
echo "✅ Done!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🌐 Now test these URLs in your browser:"
|
echo "🌐 Test these URLs in your browser:"
|
||||||
echo " https://vscode.mnemo-cards.online/"
|
echo " https://mnemo-cards.online/ (main web app)"
|
||||||
echo " https://code.mnemo-cards.online/"
|
echo " https://code.mnemo-cards.online/ (Forgejo)"
|
||||||
|
echo " https://vscode.mnemo-cards.online/ (VSCode Server)"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔑 Password: AGktOidxrah1KVC0"
|
echo "🔑 Password: AGktOidxrah1KVC0"
|
||||||
|
|
||||||
|
|
|
||||||
140
tools/deploy/deploy-nginx-configs.sh
Executable file
140
tools/deploy/deploy-nginx-configs.sh
Executable file
|
|
@ -0,0 +1,140 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to deploy generated nginx configurations to the server
|
||||||
|
# This script uses the configurations generated by generate-nginx-configs.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVER_IP="147.45.152.129"
|
||||||
|
SERVER_USER="root"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
CONFIG_DIR="$SCRIPT_DIR/generated_configs"
|
||||||
|
|
||||||
|
echo "🚀 Deploying nginx configurations to server..."
|
||||||
|
echo "Server: $SERVER_IP"
|
||||||
|
echo "Config directory: $CONFIG_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if config directory exists and has files
|
||||||
|
if [ ! -d "$CONFIG_DIR" ]; then
|
||||||
|
echo "❌ Config directory not found: $CONFIG_DIR"
|
||||||
|
echo "Run generate-nginx-configs.sh first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! "$(ls -A "$CONFIG_DIR"/*.conf 2>/dev/null)" ]; then
|
||||||
|
echo "❌ No configuration files found in $CONFIG_DIR"
|
||||||
|
echo "Run generate-nginx-configs.sh first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📤 Uploading configurations..."
|
||||||
|
scp "$CONFIG_DIR"/*.conf "$SERVER_USER@$SERVER_IP:/tmp/"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⚙️ Installing configurations on server..."
|
||||||
|
|
||||||
|
ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🛑 Stopping nginx service..."
|
||||||
|
systemctl stop nginx || true
|
||||||
|
|
||||||
|
echo "🧹 Cleaning up old configurations..."
|
||||||
|
rm -f /etc/nginx/sites-enabled/vscode*
|
||||||
|
rm -f /etc/nginx/sites-enabled/forgejo*
|
||||||
|
rm -f /etc/nginx/sites-enabled/code*
|
||||||
|
rm -f /etc/nginx/sites-enabled/mnemo*
|
||||||
|
|
||||||
|
echo "🧹 Killing any orphaned nginx processes..."
|
||||||
|
pkill -9 nginx 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
echo "📋 Installing new configurations..."
|
||||||
|
mv /tmp/vscode.mnemo-cards.online.conf /etc/nginx/sites-available/ 2>/dev/null || true
|
||||||
|
mv /tmp/code.mnemo-cards.online.conf /etc/nginx/sites-available/ 2>/dev/null || true
|
||||||
|
mv /tmp/mnemo-cards.online.conf /etc/nginx/sites-available/ 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "🔗 Creating symbolic links..."
|
||||||
|
ln -sf /etc/nginx/sites-available/vscode.mnemo-cards.online.conf /etc/nginx/sites-enabled/ 2>/dev/null || true
|
||||||
|
ln -sf /etc/nginx/sites-available/code.mnemo-cards.online.conf /etc/nginx/sites-enabled/ 2>/dev/null || true
|
||||||
|
ln -sf /etc/nginx/sites-available/mnemo-cards.online.conf /etc/nginx/sites-enabled/ 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "✅ Configurations installed"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Validating configuration..."
|
||||||
|
if /usr/sbin/nginx -t; then
|
||||||
|
echo "✅ Configuration syntax is valid"
|
||||||
|
else
|
||||||
|
echo "❌ Configuration syntax error!"
|
||||||
|
echo "Checking configuration files..."
|
||||||
|
|
||||||
|
for config in /etc/nginx/sites-enabled/*; do
|
||||||
|
echo "Testing $(basename "$config")..."
|
||||||
|
if ! /usr/sbin/nginx -t -c /etc/nginx/nginx.conf 2>&1 | grep -q "$(basename "$config")"; then
|
||||||
|
echo " ❌ Error in $(basename "$config")"
|
||||||
|
head -20 "$config"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Restoring basic configuration..."
|
||||||
|
# Create minimal working config
|
||||||
|
cat > /etc/nginx/sites-available/emergency.conf << 'EMERGENCY'
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
return 200 "nginx emergency mode\n";
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
EMERGENCY
|
||||||
|
ln -sf /etc/nginx/sites-available/emergency.conf /etc/nginx/sites-enabled/
|
||||||
|
systemctl start nginx
|
||||||
|
echo "Emergency configuration activated"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔄 Starting nginx service..."
|
||||||
|
if systemctl start nginx; then
|
||||||
|
echo "✅ nginx started successfully"
|
||||||
|
else
|
||||||
|
echo "❌ nginx failed to start!"
|
||||||
|
systemctl status nginx --no-pager
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Verifying services are accessible..."
|
||||||
|
|
||||||
|
# Test each service
|
||||||
|
SERVICES=(
|
||||||
|
"mnemo-cards.online:80:301" # Should redirect to HTTPS
|
||||||
|
"code.mnemo-cards.online:80:301"
|
||||||
|
"vscode.mnemo-cards.online:80:301"
|
||||||
|
)
|
||||||
|
|
||||||
|
for service in "${SERVICES[@]}"; do
|
||||||
|
DOMAIN=$(echo "$service" | cut -d: -f1)
|
||||||
|
PORT=$(echo "$service" | cut -d: -f2)
|
||||||
|
EXPECTED_CODE=$(echo "$service" | cut -d: -f3)
|
||||||
|
|
||||||
|
if curl -I --max-time 5 "http://$DOMAIN:$PORT/" 2>/dev/null | grep -q "HTTP/1.1 $EXPECTED_CODE"; then
|
||||||
|
echo "✅ $DOMAIN redirects correctly"
|
||||||
|
else
|
||||||
|
echo "⚠️ $DOMAIN not responding as expected"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Deployment completed!"
|
||||||
|
echo ""
|
||||||
|
echo "🌐 Services should be accessible at:"
|
||||||
|
echo " https://mnemo-cards.online/ (main web app)"
|
||||||
|
echo " https://code.mnemo-cards.online/ (Forgejo)"
|
||||||
|
echo " https://vscode.mnemo-cards.online/ (VSCode Server)"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 To check status: ./check-nginx.sh"
|
||||||
|
echo "🔧 To regenerate configs: ./generate-nginx-configs.sh"
|
||||||
|
|
@ -8,80 +8,297 @@ SERVER_IP="147.45.152.129"
|
||||||
SERVER_USER="root"
|
SERVER_USER="root"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
VSCODE_NGINX_CONF="$PROJECT_ROOT/mnemo_cards_web_v2/deploy/vscode-nginx.conf"
|
|
||||||
|
|
||||||
echo "🚀 Deploying VSCode nginx configuration..."
|
echo "🚀 Deploying nginx configurations to server..."
|
||||||
echo "Server: $SERVER_IP"
|
echo "Server: $SERVER_IP"
|
||||||
echo "Config file: $VSCODE_NGINX_CONF"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Check if config file exists
|
# Function to generate nginx configuration for a service
|
||||||
if [ ! -f "$VSCODE_NGINX_CONF" ]; then
|
generate_nginx_config() {
|
||||||
echo "❌ Config file not found: $VSCODE_NGINX_CONF"
|
local domain=$1
|
||||||
exit 1
|
local upstream_port=$2
|
||||||
fi
|
local service_name=$3
|
||||||
|
local rate_limit_zone=$4
|
||||||
|
local rate_limit_burst=$5
|
||||||
|
|
||||||
echo "📤 Uploading nginx configuration..."
|
cat << EOF
|
||||||
scp "$VSCODE_NGINX_CONF" "$SERVER_USER@$SERVER_IP:/tmp/vscode-nginx.conf"
|
# Nginx configuration for $domain
|
||||||
|
# Generated by deploy script
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name $domain;
|
||||||
|
return 301 https://\$server_name\$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name $domain;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# Client settings
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add rate limiting for VSCode
|
||||||
|
if [ "$service_name" = "vscode" ]; then
|
||||||
|
cat << EOF
|
||||||
|
# Rate limiting for VSCode
|
||||||
|
limit_req zone=$rate_limit_zone burst=$rate_limit_burst nodelay;
|
||||||
|
|
||||||
|
# Static files - no rate limiting
|
||||||
|
location ~ ^/(static|out|node_modules)/ {
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file extensions - no rate limiting
|
||||||
|
location ~ \.(js|css|woff|woff2|ttf|eot|png|jpg|jpeg|gif|svg|ico|webp|map|json)$ {
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Special rate limiting for login attempts
|
||||||
|
location /login {
|
||||||
|
limit_req zone=vscode_login burst=2 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main proxy location
|
||||||
|
cat << EOF
|
||||||
|
# Proxy to $service_name
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [ "$service_name" = "vscode" ]; then
|
||||||
|
cat << EOF
|
||||||
|
location / {
|
||||||
|
limit_req zone=$rate_limit_zone burst=$rate_limit_burst nodelay;
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat << EOF
|
||||||
|
location / {
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
echo " gzip on;"
|
||||||
|
echo " gzip_vary on;"
|
||||||
|
echo " gzip_min_length 1024;"
|
||||||
|
echo " gzip_proxied expired no-cache no-store private auth;"
|
||||||
|
echo " gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript;"
|
||||||
|
echo ""
|
||||||
|
echo " # Security - deny access to hidden files"
|
||||||
|
echo " location ~ /\. {"
|
||||||
|
echo " deny all;"
|
||||||
|
echo " }"
|
||||||
|
echo "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate configurations for all services
|
||||||
|
echo "📝 Generating nginx configurations..."
|
||||||
|
|
||||||
|
# VSCode configuration
|
||||||
|
generate_nginx_config "vscode.mnemo-cards.online" "8443" "vscode" "vscode_general" "50" > /tmp/vscode-nginx.conf
|
||||||
|
|
||||||
|
# Forgejo configuration
|
||||||
|
generate_nginx_config "code.mnemo-cards.online" "3000" "forgejo" "" "" > /tmp/forgejo-nginx.conf
|
||||||
|
|
||||||
|
# Main web app configuration
|
||||||
|
cat > /tmp/mnemo_cards_main-nginx.conf << 'EOF'
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name mnemo-cards.online www.mnemo-cards.online;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name mnemo-cards.online www.mnemo-cards.online;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
|
||||||
|
# Client settings
|
||||||
|
client_max_body_size 1000M;
|
||||||
|
|
||||||
|
root /var/www/mnemo_cards;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# ACME challenge for certificate renewal
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/html;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript;
|
||||||
|
|
||||||
|
# Security - deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "📤 Uploading configurations to server..."
|
||||||
|
scp /tmp/vscode-nginx.conf "$SERVER_USER@$SERVER_IP:/tmp/"
|
||||||
|
scp /tmp/forgejo-nginx.conf "$SERVER_USER@$SERVER_IP:/tmp/"
|
||||||
|
scp /tmp/mnemo_cards_main-nginx.conf "$SERVER_USER@$SERVER_IP:/tmp/"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "⚙️ Installing configuration on server..."
|
echo "⚙️ Installing configurations on server..."
|
||||||
|
|
||||||
ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
ssh "$SERVER_USER@$SERVER_IP" << 'ENDSSH'
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "📋 Moving config to nginx sites-available..."
|
echo "🛑 Stopping nginx service..."
|
||||||
|
systemctl stop nginx
|
||||||
|
|
||||||
|
echo "🧹 Cleaning up old configurations..."
|
||||||
|
rm -f /etc/nginx/sites-enabled/vscode*
|
||||||
|
rm -f /etc/nginx/sites-enabled/forgejo*
|
||||||
|
rm -f /etc/nginx/sites-enabled/mnemo_cards*
|
||||||
|
|
||||||
|
echo "📋 Installing new configurations..."
|
||||||
mv /tmp/vscode-nginx.conf /etc/nginx/sites-available/vscode.mnemo-cards.online
|
mv /tmp/vscode-nginx.conf /etc/nginx/sites-available/vscode.mnemo-cards.online
|
||||||
|
mv /tmp/forgejo-nginx.conf /etc/nginx/sites-available/code.mnemo-cards.online
|
||||||
|
mv /tmp/mnemo_cards_main-nginx.conf /etc/nginx/sites-available/mnemo-cards.online
|
||||||
|
|
||||||
echo "🔗 Creating symbolic link in sites-enabled..."
|
echo "🔗 Creating symbolic links..."
|
||||||
ln -sf /etc/nginx/sites-available/vscode.mnemo-cards.online /etc/nginx/sites-enabled/vscode.mnemo-cards.online
|
ln -sf /etc/nginx/sites-available/vscode.mnemo-cards.online /etc/nginx/sites-enabled/
|
||||||
|
ln -sf /etc/nginx/sites-available/code.mnemo-cards.online /etc/nginx/sites-enabled/
|
||||||
|
ln -sf /etc/nginx/sites-available/mnemo-cards.online /etc/nginx/sites-enabled/
|
||||||
|
|
||||||
echo "✅ Configuration installed"
|
echo "✅ Configurations installed"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 Checking nginx configuration syntax..."
|
echo "📊 Checking nginx configuration syntax..."
|
||||||
/usr/sbin/nginx -t
|
if /usr/sbin/nginx -t; then
|
||||||
|
echo "✅ Configuration syntax is valid"
|
||||||
echo ""
|
|
||||||
echo "🔄 Reloading nginx..."
|
|
||||||
systemctl reload nginx
|
|
||||||
|
|
||||||
echo "✅ nginx reloaded successfully"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Checking SSL certificates..."
|
|
||||||
if [ -d "/etc/letsencrypt/live/vscode.mnemo-cards.online" ]; then
|
|
||||||
echo "✅ Let's Encrypt certificates found"
|
|
||||||
ls -la /etc/letsencrypt/live/vscode.mnemo-cards.online/
|
|
||||||
else
|
else
|
||||||
echo "⚠️ Let's Encrypt certificates not found"
|
echo "❌ Configuration syntax error!"
|
||||||
echo "You may need to obtain certificates with:"
|
echo "Restoring previous configurations..."
|
||||||
echo " sudo certbot certonly --standalone -d vscode.mnemo-cards.online"
|
systemctl start nginx
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 Checking rate limiting zones in main nginx config..."
|
echo "🔄 Starting nginx service..."
|
||||||
if grep -q "vscode_general" /etc/nginx/nginx.conf; then
|
systemctl start nginx
|
||||||
echo "✅ Rate limiting zones are configured"
|
|
||||||
|
if systemctl is-active --quiet nginx; then
|
||||||
|
echo "✅ nginx started successfully"
|
||||||
else
|
else
|
||||||
echo "⚠️ Rate limiting zones not found in main config"
|
echo "❌ nginx failed to start!"
|
||||||
echo "Adding rate limiting zones..."
|
systemctl status nginx --no-pager
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Backup current config
|
echo ""
|
||||||
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
|
echo "📊 Checking SSL certificates..."
|
||||||
|
if [ -d "/etc/letsencrypt/live/mnemo-cards.online" ]; then
|
||||||
# Add rate limiting zones in http block
|
echo "✅ Let's Encrypt certificates found"
|
||||||
sed -i '/http {/a\ # Rate limiting zones for VSCode Server\n limit_req_zone $binary_remote_addr zone=vscode_general:10m rate=100r/m;\n limit_req_zone $binary_remote_addr zone=vscode_login:10m rate=5r/m;' /etc/nginx/nginx.conf
|
# Ensure correct permissions
|
||||||
|
chmod 755 /etc/letsencrypt/archive
|
||||||
echo "✅ Rate limiting zones added"
|
chmod 755 /etc/letsencrypt/live
|
||||||
|
find /etc/letsencrypt -type d -exec chmod 755 {} \;
|
||||||
echo ""
|
find /etc/letsencrypt -type f -exec chmod 644 {} \;
|
||||||
echo "📊 Testing updated configuration..."
|
chmod 600 /etc/letsencrypt/archive/mnemo-cards.online/privkey*.pem
|
||||||
/usr/sbin/nginx -t
|
chmod 600 /etc/letsencrypt/live/mnemo-cards.online/privkey.pem
|
||||||
|
else
|
||||||
echo ""
|
echo "⚠️ Let's Encrypt certificates not found"
|
||||||
echo "🔄 Reloading nginx again..."
|
|
||||||
systemctl reload nginx
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
@ -89,13 +306,10 @@ ENDSSH
|
||||||
echo ""
|
echo ""
|
||||||
echo "✅ Done!"
|
echo "✅ Done!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🌐 VSCode Server should now be accessible at:"
|
echo "🌐 Services should now be accessible at:"
|
||||||
echo " https://vscode.mnemo-cards.online/"
|
echo " https://mnemo-cards.online/ (main web app)"
|
||||||
echo " https://code.mnemo-cards.online/ (same service)"
|
echo " https://code.mnemo-cards.online/ (Forgejo)"
|
||||||
|
echo " https://vscode.mnemo-cards.online/ (VSCode Server)"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔑 Password: AGktOidxrah1KVC0"
|
echo "🔑 VSCode Password: AGktOidxrah1KVC0"
|
||||||
echo ""
|
|
||||||
echo "📝 If you get SSL errors, you may need to obtain certificates:"
|
|
||||||
echo " ssh root@$SERVER_IP"
|
|
||||||
echo " sudo certbot certonly --standalone -d vscode.mnemo-cards.online -d code.mnemo-cards.online"
|
|
||||||
|
|
||||||
|
|
|
||||||
245
tools/deploy/generate-nginx-configs.sh
Executable file
245
tools/deploy/generate-nginx-configs.sh
Executable file
|
|
@ -0,0 +1,245 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to generate all nginx configurations for the project
|
||||||
|
# This ensures consistent configuration across all deployments
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
OUTPUT_DIR="$SCRIPT_DIR/generated_configs"
|
||||||
|
|
||||||
|
echo "🔧 Generating nginx configurations..."
|
||||||
|
echo "Output directory: $OUTPUT_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create output directory
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
# Function to generate nginx configuration for a service
|
||||||
|
generate_nginx_config() {
|
||||||
|
local domain=$1
|
||||||
|
local upstream_port=$2
|
||||||
|
local service_name=$3
|
||||||
|
local rate_limit_zone=$4
|
||||||
|
local rate_limit_burst=$5
|
||||||
|
local output_file="$OUTPUT_DIR/$domain.conf"
|
||||||
|
|
||||||
|
echo "📝 Generating config for $domain (port $upstream_port)..."
|
||||||
|
|
||||||
|
cat > "$output_file" << EOF
|
||||||
|
# Nginx configuration for $domain
|
||||||
|
# Generated by generate-nginx-configs.sh on $(date)
|
||||||
|
# Service: $service_name
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name $domain;
|
||||||
|
return 301 https://\$server_name\$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name $domain;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add service-specific settings
|
||||||
|
case $service_name in
|
||||||
|
vscode)
|
||||||
|
cat >> "$output_file" << EOF
|
||||||
|
# VSCode Server specific settings
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Rate limiting for VSCode
|
||||||
|
limit_req_zone \$binary_remote_addr zone=vscode_general:10m rate=100r/m;
|
||||||
|
limit_req_zone \$binary_remote_addr zone=vscode_login:10m rate=5r/m;
|
||||||
|
|
||||||
|
# Static files - no rate limiting
|
||||||
|
location ~ ^/(static|out|node_modules)/ {
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file extensions - no rate limiting
|
||||||
|
location ~ \.(js|css|woff|woff2|ttf|eot|png|jpg|jpeg|gif|svg|ico|webp|map|json)$ {
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Special rate limiting for login attempts
|
||||||
|
location /login {
|
||||||
|
limit_req zone=vscode_login burst=2 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main proxy location with rate limiting
|
||||||
|
location / {
|
||||||
|
limit_req zone=vscode_general burst=50 nodelay;
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
forgejo)
|
||||||
|
cat >> "$output_file" << EOF
|
||||||
|
# Forgejo (Git) specific settings
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Main proxy location
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
webapp)
|
||||||
|
cat >> "$output_file" << EOF
|
||||||
|
# Web app specific settings
|
||||||
|
client_max_body_size 1000M;
|
||||||
|
|
||||||
|
root /var/www/mnemo_cards;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files \$uri \$uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# ACME challenge for certificate renewal
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/html;
|
||||||
|
try_files \$uri =404;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Common proxy settings for services that don't have custom proxy blocks
|
||||||
|
if [ "$service_name" = "vscode" ]; then
|
||||||
|
cat >> "$output_file" << EOF
|
||||||
|
proxy_pass http://127.0.0.1:$upstream_port;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Gzip compression for all services
|
||||||
|
cat >> "$output_file" << EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression (configured globally in nginx.conf)
|
||||||
|
|
||||||
|
# Security - deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "✅ Generated $output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate configurations for all services
|
||||||
|
|
||||||
|
# Main web application
|
||||||
|
generate_nginx_config "mnemo-cards.online" "" "webapp"
|
||||||
|
|
||||||
|
# VSCode Server
|
||||||
|
generate_nginx_config "vscode.mnemo-cards.online" "8443" "vscode"
|
||||||
|
|
||||||
|
# Forgejo (Git server)
|
||||||
|
generate_nginx_config "code.mnemo-cards.online" "3000" "forgejo"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Validating generated configurations..."
|
||||||
|
|
||||||
|
# Test each configuration
|
||||||
|
for config in "$OUTPUT_DIR"/*.conf; do
|
||||||
|
echo "Testing $(basename "$config")..."
|
||||||
|
/usr/sbin/nginx -t -c /etc/nginx/nginx.conf -g "include $config;" 2>/dev/null && echo "✅ Valid" || echo "❌ Invalid"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ All configurations generated successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "📁 Generated files in: $OUTPUT_DIR"
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Use deploy-nginx-configs.sh to deploy these configurations to the server"
|
||||||
63
tools/deploy/generated_configs/code.mnemo-cards.online.conf
Normal file
63
tools/deploy/generated_configs/code.mnemo-cards.online.conf
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Nginx configuration for code.mnemo-cards.online
|
||||||
|
# Generated by generate-nginx-configs.sh on Sun Nov 23 02:51:54 MSK 2025
|
||||||
|
# Service: forgejo
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name code.mnemo-cards.online;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name code.mnemo-cards.online;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# Forgejo (Git) specific settings
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Main proxy location
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:3000;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript;
|
||||||
|
|
||||||
|
# Security - deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
61
tools/deploy/generated_configs/mnemo-cards.online.conf
Normal file
61
tools/deploy/generated_configs/mnemo-cards.online.conf
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Nginx configuration for mnemo-cards.online
|
||||||
|
# Generated by generate-nginx-configs.sh on Sun Nov 23 02:51:54 MSK 2025
|
||||||
|
# Service: webapp
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name mnemo-cards.online;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name mnemo-cards.online;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# Web app specific settings
|
||||||
|
client_max_body_size 1000M;
|
||||||
|
|
||||||
|
root /var/www/mnemo_cards;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# ACME challenge for certificate renewal
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/html;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript;
|
||||||
|
|
||||||
|
# Security - deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
122
tools/deploy/generated_configs/vscode.mnemo-cards.online.conf
Normal file
122
tools/deploy/generated_configs/vscode.mnemo-cards.online.conf
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
# Nginx configuration for vscode.mnemo-cards.online
|
||||||
|
# Generated by generate-nginx-configs.sh on Sun Nov 23 02:51:54 MSK 2025
|
||||||
|
# Service: vscode
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name vscode.mnemo-cards.online;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name vscode.mnemo-cards.online;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/mnemo-cards.online/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/mnemo-cards.online/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# VSCode Server specific settings
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Rate limiting for VSCode
|
||||||
|
limit_req_zone $binary_remote_addr zone=vscode_general:10m rate=100r/m;
|
||||||
|
limit_req_zone $binary_remote_addr zone=vscode_login:10m rate=5r/m;
|
||||||
|
|
||||||
|
# Static files - no rate limiting
|
||||||
|
location ~ ^/(static|out|node_modules)/ {
|
||||||
|
proxy_pass http://127.0.0.1:8443;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file extensions - no rate limiting
|
||||||
|
location ~ \.(js|css|woff|woff2|ttf|eot|png|jpg|jpeg|gif|svg|ico|webp|map|json)$ {
|
||||||
|
proxy_pass http://127.0.0.1:8443;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_cache_valid 200 1h;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Special rate limiting for login attempts
|
||||||
|
location /login {
|
||||||
|
limit_req zone=vscode_login burst=2 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:8443;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main proxy location with rate limiting
|
||||||
|
location / {
|
||||||
|
limit_req zone=vscode_general burst=50 nodelay;
|
||||||
|
proxy_pass http://127.0.0.1:8443;
|
||||||
|
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;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript;
|
||||||
|
|
||||||
|
# Security - deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue