.
This commit is contained in:
parent
401292539b
commit
c9fe5847da
@ -111,4 +111,4 @@ COPY --from=builder /repo/apps/server/package.json ./apps/server/package.json
|
|||||||
|
|
||||||
EXPOSE 3002
|
EXPOSE 3002
|
||||||
#CMD ["pnpm","exec", "node", "--env-file=apps/server/dist/.env", "apps/server/dist/index.js"]
|
#CMD ["pnpm","exec", "node", "--env-file=apps/server/dist/.env", "apps/server/dist/index.js"]
|
||||||
CMD ["pnpm","exec", "node", "apps/server/dist/index.js"]
|
CMD ["pnpm", "exec", "node", "apps/server/dist/index.js"]
|
||||||
|
|||||||
@ -8,7 +8,6 @@ API_PORT=3002
|
|||||||
|
|
||||||
|
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
HOST=0.0.0.0
|
|
||||||
PORT=3002
|
PORT=3002
|
||||||
FRONTEND_URL=https://aana.factuges.app
|
FRONTEND_URL=https://aana.factuges.app
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
HOST=0.0.0.0
|
API_PORT=3002
|
||||||
SERVER_PORT=3002
|
|
||||||
FRONTEND_URL=http://localhost:5173
|
FRONTEND_URL=http://localhost:5173
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,7 @@
|
|||||||
# Core del servidor HTTP
|
# Core del servidor HTTP
|
||||||
# ───────────────────────────────
|
# ───────────────────────────────
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
HOST=0.0.0.0
|
API_PORT=3002
|
||||||
SERVER_PORT=3002
|
|
||||||
|
|
||||||
# URL pública del frontend (CORS).
|
# URL pública del frontend (CORS).
|
||||||
# En dev se puede permitir todo con '*'
|
# En dev se puede permitir todo con '*'
|
||||||
|
|||||||
@ -13,7 +13,6 @@ DB_ROOT_PASS=verysecret
|
|||||||
TRAEFIK_ENTRYPOINT=web
|
TRAEFIK_ENTRYPOINT=web
|
||||||
|
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
HOST=0.0.0.0
|
|
||||||
PORT=3002
|
PORT=3002
|
||||||
FRONTEND_URL=http://factuges.rodax-software.local
|
FRONTEND_URL=http://factuges.rodax-software.local
|
||||||
|
|
||||||
|
|||||||
45
apps/server/.env.rodax
Normal file
45
apps/server/.env.rodax
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# ───────────────────────────────
|
||||||
|
# Identidad de la compañía
|
||||||
|
# ───────────────────────────────
|
||||||
|
COMPANY=rodax
|
||||||
|
CTE_COMPANY_ID=5e4dc5b3-96b9-4968-9490-14bd032fec5f
|
||||||
|
|
||||||
|
# Dominios
|
||||||
|
DOMAIN=factuges.rodax-software.local
|
||||||
|
|
||||||
|
# ───────────────────────────────
|
||||||
|
# Base de datos (Sequelize / MySQL-MariaDB)
|
||||||
|
# ───────────────────────────────
|
||||||
|
DB_ROOT_PASS=verysecret
|
||||||
|
DB_USER=rodax_usr
|
||||||
|
DB_PASS=supersecret
|
||||||
|
DB_NAME=rodax_db
|
||||||
|
DB_PORT=3306
|
||||||
|
|
||||||
|
# Log de Sequelize (true|false)
|
||||||
|
DB_LOGGING=false
|
||||||
|
|
||||||
|
# Alterar estructura BD
|
||||||
|
DB_SYNC_MODE=none # none | alter | force
|
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────
|
||||||
|
# API
|
||||||
|
# ───────────────────────────────
|
||||||
|
API_PORT=3002
|
||||||
|
API_IMAGE=factuges-server:rodax-latest
|
||||||
|
|
||||||
|
# Plantillas
|
||||||
|
TEMPLATES_PATH=/repo/apps/server/templates
|
||||||
|
|
||||||
|
# Chrome executable path (Puppeteer)
|
||||||
|
PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome
|
||||||
|
|
||||||
|
# URL pública del frontend (CORS)
|
||||||
|
FRONTEND_URL=factuges.rodax-software.local
|
||||||
|
|
||||||
|
# Tiempo máximo para cada warmup() de un módulo, en milisegundos.
|
||||||
|
WARMUP_TIMEOUT_MS=10000
|
||||||
|
|
||||||
|
# Si es true, un fallo de warmup aborta el arranque. Si es false, continúa con warning.
|
||||||
|
WARMUP_STRICT=false
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-server",
|
"name": "@erp/factuges-server",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsup src/index.ts --config tsup.config.ts",
|
"build": "tsup src/index.ts --config tsup.config.ts",
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export function createApp(): Application {
|
|||||||
app.use(cors(ENV.NODE_ENV === "development" ? devCors : prodCors));
|
app.use(cors(ENV.NODE_ENV === "development" ? devCors : prodCors));
|
||||||
app.options("*", cors(ENV.NODE_ENV === "development" ? devCors : prodCors));
|
app.options("*", cors(ENV.NODE_ENV === "development" ? devCors : prodCors));
|
||||||
|
|
||||||
app.set("port", process.env.SERVER_PORT ?? 3002);
|
app.set("port", process.env.API_PORT ?? 3002);
|
||||||
|
|
||||||
// Oculta la cabecera x-powered-by
|
// Oculta la cabecera x-powered-by
|
||||||
app.disable("x-powered-by");
|
app.disable("x-powered-by");
|
||||||
|
|||||||
@ -13,8 +13,7 @@ const NODE_ENV = (process.env.NODE_ENV as NodeEnv) ?? "development";
|
|||||||
const isProd = NODE_ENV === "production";
|
const isProd = NODE_ENV === "production";
|
||||||
const isDev = NODE_ENV === "development";
|
const isDev = NODE_ENV === "development";
|
||||||
|
|
||||||
const HOST = process.env.HOST ?? "0.0.0.0";
|
const API_PORT = asNumber(process.env.API_PORT, 3002);
|
||||||
const SERVER_PORT = asNumber(process.env.SERVER_PORT, 3002);
|
|
||||||
|
|
||||||
// En producción exigimos FRONTEND_URL definido (según requisitos actuales).
|
// En producción exigimos FRONTEND_URL definido (según requisitos actuales).
|
||||||
const FRONTEND_URL = isProd
|
const FRONTEND_URL = isProd
|
||||||
@ -48,8 +47,7 @@ const TRUST_PROXY = asNumber(process.env.TRUST_PROXY, 0);
|
|||||||
|
|
||||||
export const ENV = {
|
export const ENV = {
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
HOST,
|
API_PORT,
|
||||||
SERVER_PORT,
|
|
||||||
FRONTEND_URL,
|
FRONTEND_URL,
|
||||||
DATABASE_URL,
|
DATABASE_URL,
|
||||||
DB_DIALECT,
|
DB_DIALECT,
|
||||||
|
|||||||
@ -20,8 +20,8 @@ z.config(z.locales.es());
|
|||||||
export const currentState = {
|
export const currentState = {
|
||||||
launchedAt: DateTime.now(),
|
launchedAt: DateTime.now(),
|
||||||
appPath: process.cwd(),
|
appPath: process.cwd(),
|
||||||
host: ENV.HOST,
|
hosts: "0.0.0.0",
|
||||||
port: ENV.SERVER_PORT,
|
port: ENV.API_PORT,
|
||||||
environment: ENV.NODE_ENV,
|
environment: ENV.NODE_ENV,
|
||||||
connections: {} as Record<string, unknown>,
|
connections: {} as Record<string, unknown>,
|
||||||
};
|
};
|
||||||
@ -91,12 +91,11 @@ const serverError = (error: NodeJS.ErrnoException) => {
|
|||||||
logger.error("⛔️ Server wasn't able to start properly.", {
|
logger.error("⛔️ Server wasn't able to start properly.", {
|
||||||
label: "serverError0",
|
label: "serverError0",
|
||||||
error,
|
error,
|
||||||
host: ENV.HOST,
|
port: ENV.API_PORT,
|
||||||
port: ENV.SERVER_PORT,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error.code === "EADDRINUSE") {
|
if (error.code === "EADDRINUSE") {
|
||||||
logger.error(`Port ${ENV.SERVER_PORT} already in use`, { error, label: "serverError1" });
|
logger.error(`Port ${ENV.API_PORT} already in use`, { error, label: "serverError1" });
|
||||||
} else {
|
} else {
|
||||||
logger.error(error.message, { error, label: "serverError2" });
|
logger.error(error.message, { error, label: "serverError2" });
|
||||||
}
|
}
|
||||||
@ -211,8 +210,7 @@ process.on("uncaughtException", async (error: Error) => {
|
|||||||
|
|
||||||
// Mostrar variables de entorno
|
// Mostrar variables de entorno
|
||||||
logger.info(`Environment: ${currentState.environment}`);
|
logger.info(`Environment: ${currentState.environment}`);
|
||||||
logger.info(`HOST: ${ENV.HOST}`);
|
logger.info(`API_PORT: ${ENV.API_PORT}`);
|
||||||
logger.info(`SERVER_PORT: ${ENV.SERVER_PORT}`);
|
|
||||||
logger.info(`API_BASE_PATH: ${API_BASE_PATH}`);
|
logger.info(`API_BASE_PATH: ${API_BASE_PATH}`);
|
||||||
|
|
||||||
logger.info(`FRONTEND_URL: ${ENV.FRONTEND_URL}`);
|
logger.info(`FRONTEND_URL: ${ENV.FRONTEND_URL}`);
|
||||||
@ -268,7 +266,6 @@ process.on("uncaughtException", async (error: Error) => {
|
|||||||
|
|
||||||
// URLs de acceso útiles
|
// URLs de acceso útiles
|
||||||
logger.info(`⚡️ Server accessible at: http://localhost:${currentState.port}`);
|
logger.info(`⚡️ Server accessible at: http://localhost:${currentState.port}`);
|
||||||
logger.info(`⚡️ Server accessible at: http://${currentState.host}:${currentState.port}`);
|
|
||||||
for (const address of addresses) {
|
for (const address of addresses) {
|
||||||
logger.info(`⚡️ Server accessible at: http://${address}:${currentState.port}`);
|
logger.info(`⚡️ Server accessible at: http://${address}:${currentState.port}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-web",
|
"name": "@erp/factuges-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host --clearScreen false",
|
"dev": "vite --host --clearScreen false",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/auth",
|
"name": "@erp/auth",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -7,8 +7,8 @@ export function mockUser(req: RequestWithAuth, _res: Response, next: NextFunctio
|
|||||||
req.user = {
|
req.user = {
|
||||||
userId: UniqueID.create("9e4dc5b3-96b9-4968-9490-14bd032fec5f").data,
|
userId: UniqueID.create("9e4dc5b3-96b9-4968-9490-14bd032fec5f").data,
|
||||||
email: EmailAddress.create("dev@example.com").data,
|
email: EmailAddress.create("dev@example.com").data,
|
||||||
companyId: UniqueID.create("019a9667-6a65-767a-a737-48234ee50a3a").data,
|
companyId: UniqueID.create("5e4dc5b3-96b9-4968-9490-14bd032fec5f").data,
|
||||||
companySlug: "alonsoysal",
|
companySlug: "rodax",
|
||||||
roles: ["admin"],
|
roles: ["admin"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/core",
|
"name": "@erp/core",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -12,24 +12,25 @@
|
|||||||
// Nota: Todos los nombres de tipos/clases/archivos en inglés; comentarios en castellano.
|
// Nota: Todos los nombres de tipos/clases/archivos en inglés; comentarios en castellano.
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DomainValidationError,
|
type DomainValidationError,
|
||||||
|
type ValidationErrorCollection,
|
||||||
isDomainValidationError,
|
isDomainValidationError,
|
||||||
isValidationErrorCollection,
|
isValidationErrorCollection,
|
||||||
ValidationErrorCollection,
|
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DuplicateEntityError,
|
type DuplicateEntityError,
|
||||||
EntityNotFoundError,
|
type EntityNotFoundError,
|
||||||
isDuplicateEntityError,
|
isDuplicateEntityError,
|
||||||
isEntityNotFoundError,
|
isEntityNotFoundError,
|
||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
import {
|
import {
|
||||||
InfrastructureRepositoryError,
|
type InfrastructureRepositoryError,
|
||||||
InfrastructureUnavailableError,
|
type InfrastructureUnavailableError,
|
||||||
isInfrastructureRepositoryError,
|
isInfrastructureRepositoryError,
|
||||||
isInfrastructureUnavailableError,
|
isInfrastructureUnavailableError,
|
||||||
} from "../errors";
|
} from "../errors";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiError,
|
ApiError,
|
||||||
ConflictApiError,
|
ConflictApiError,
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import type { Criteria } from "@repo/rdx-criteria/server";
|
||||||
import { NextFunction, Request, Response } from "express";
|
import type { NextFunction, Request, Response } from "express";
|
||||||
import { ApiError, ForbiddenApiError, UnauthorizedApiError, ValidationApiError } from "./errors";
|
|
||||||
import { ExpressController } from "./express-controller";
|
import {
|
||||||
|
type ApiError,
|
||||||
|
ForbiddenApiError,
|
||||||
|
UnauthorizedApiError,
|
||||||
|
ValidationApiError,
|
||||||
|
} from "./errors";
|
||||||
|
import type { ExpressController } from "./express-controller";
|
||||||
|
|
||||||
export type GuardResultLike = { isFailure: boolean; error?: ApiError };
|
export type GuardResultLike = { isFailure: boolean; error?: ApiError };
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customer-invoices",
|
"name": "@erp/customer-invoices",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
BIN
modules/customer-invoices/templates/rodax/logo2.jpg
Normal file
BIN
modules/customer-invoices/templates/rodax/logo2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customers",
|
"name": "@erp/customers",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/doc-numbering",
|
"name": "@erp/doc-numbering",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-criteria",
|
"name": "@repo/rdx-criteria",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-ddd",
|
"name": "@repo/rdx-ddd",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-logger",
|
"name": "@repo/rdx-logger",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-utils",
|
"name": "@repo/rdx-utils",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -42,6 +42,17 @@ fi
|
|||||||
|
|
||||||
COMPANY="$1"
|
COMPANY="$1"
|
||||||
|
|
||||||
|
SSH_USER="rodax"
|
||||||
|
SSH_HOST="vps-2.rodax-software.com"
|
||||||
|
SSH_PORT="49152"
|
||||||
|
|
||||||
|
# Override por compañía específica
|
||||||
|
if [[ "$COMPANY" == "rodax" ]]; then
|
||||||
|
SSH_USER="rodax"
|
||||||
|
SSH_HOST="factuges.rodax-software.local"
|
||||||
|
SSH_PORT="22"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Parseo de flags ---
|
# --- Parseo de flags ---
|
||||||
shift # quitamos el <company>, ahora solo quedan flags
|
shift # quitamos el <company>, ahora solo quedan flags
|
||||||
|
|
||||||
@ -221,19 +232,26 @@ EOF
|
|||||||
echo "📦 API manifest generado en ${OUT_API_DIR}/manifest-v${API_VERSION}-${DATE}.json"
|
echo "📦 API manifest generado en ${OUT_API_DIR}/manifest-v${API_VERSION}-${DATE}.json"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$LOAD" == true ]]; then
|
|
||||||
echo "📥 Cargando imagen en producción vps-2.rodax-software.com..."
|
|
||||||
[[ "$MODE" == "web" || "$MODE" == "all" ]] && scp -r -P 49152 ${OUT_WEB_DIR} rodax@vps-2.rodax-software.com:/opt/factuges/${COMPANY}/
|
|
||||||
[[ "$MODE" == "api" || "$MODE" == "all" ]] && scp -r -P 49152 ${OUT_API_DIR} rodax@vps-2.rodax-software.com:/opt/factuges/${COMPANY}/
|
|
||||||
[[ "$MODE" == "api" || "$MODE" == "all" ]] && scp -r -P 49152 ${TEMPLATES_DIR} rodax@vps-2.rodax-software.com:/opt/factuges/${COMPANY}/
|
|
||||||
|
|
||||||
[[ "$MODE" == "api" || "$MODE" == "all" ]] && RESULT=$(ssh -p 49152 rodax@vps-2.rodax-software.com "docker load -i /opt/factuges/${COMPANY}/api/$(basename ${TAR_FILE_LATEST})")
|
if [[ "$LOAD" == true ]]; then
|
||||||
[[ "$MODE" == "api" || "$MODE" == "all" ]] && echo $RESULT
|
echo "📥 Cargando imagen en producción ${SSH_HOST}..."
|
||||||
#docker load -i "${TAR_FILE_V}"
|
|
||||||
|
[[ "$MODE" == "web" || "$MODE" == "all" ]] && scp -r -P "${SSH_PORT}" "${OUT_WEB_DIR}" "${SSH_USER}@${SSH_HOST}:/opt/factuges/${COMPANY}/"
|
||||||
|
[[ "$MODE" == "api" || "$MODE" == "all" ]] && scp -r -P "${SSH_PORT}" "${OUT_API_DIR}" "${SSH_USER}@${SSH_HOST}:/opt/factuges/${COMPANY}/"
|
||||||
|
[[ "$MODE" == "api" || "$MODE" == "all" ]] && scp -r -P "${SSH_PORT}" "${TEMPLATES_DIR}" "${SSH_USER}@${SSH_HOST}:/opt/factuges/${COMPANY}/"
|
||||||
|
|
||||||
|
if [[ "$MODE" == "api" || "$MODE" == "all" ]]; then
|
||||||
|
RESULT=$(ssh -p "${SSH_PORT}" "${SSH_USER}@${SSH_HOST}" \
|
||||||
|
"docker load -i /opt/factuges/${COMPANY}/api/$(basename "${TAR_FILE_LATEST}")")
|
||||||
|
echo "${RESULT}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "✅ Imagen cargada en producción"
|
echo "✅ Imagen cargada en producción"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# 3️⃣ Resumen
|
# 3️⃣ Resumen
|
||||||
# =====================================================
|
# =====================================================
|
||||||
|
|||||||
@ -1,78 +0,0 @@
|
|||||||
services:
|
|
||||||
# MongoDB database for persistent storage (optional - SQLite is used by default)
|
|
||||||
mongodb:
|
|
||||||
image: mongo:8.0
|
|
||||||
container_name: caddymanager-mongodb
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- MONGO_INITDB_ROOT_USERNAME=mongoadmin
|
|
||||||
- MONGO_INITDB_ROOT_PASSWORD=someSecretPassword # Change for production!
|
|
||||||
ports:
|
|
||||||
- "27017:27017" # Expose for local dev, remove for production
|
|
||||||
volumes:
|
|
||||||
- mongodb_data:/data/db
|
|
||||||
networks:
|
|
||||||
- caddymanager
|
|
||||||
profiles:
|
|
||||||
- mongodb # Use 'docker-compose --profile mongodb up' to include MongoDB
|
|
||||||
|
|
||||||
# Backend API server
|
|
||||||
backend:
|
|
||||||
image: caddymanager/caddymanager-backend:latest
|
|
||||||
container_name: caddymanager-backend
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- PORT=3000
|
|
||||||
# Database Engine Configuration (defaults to SQLite)
|
|
||||||
- DB_ENGINE=sqlite # Options: 'sqlite' or 'mongodb'
|
|
||||||
# SQLite Configuration (used when DB_ENGINE=sqlite)
|
|
||||||
- SQLITE_DB_PATH=/app/data/caddymanager.sqlite
|
|
||||||
# MongoDB Configuration (used when DB_ENGINE=mongodb)
|
|
||||||
- MONGODB_URI=mongodb://mongoadmin:someSecretPassword@mongodb:27017/caddymanager?authSource=admin
|
|
||||||
- CORS_ORIGIN=http://localhost:80
|
|
||||||
- LOG_LEVEL=debug
|
|
||||||
- CADDY_SANDBOX_URL=http://localhost:2019
|
|
||||||
- PING_INTERVAL=30000
|
|
||||||
- PING_TIMEOUT=2000
|
|
||||||
- AUDIT_LOG_MAX_SIZE_MB=100
|
|
||||||
- AUDIT_LOG_RETENTION_DAYS=90
|
|
||||||
- METRICS_HISTORY_MAX=1000 # Optional: max number of in-memory metric history snapshots to keep
|
|
||||||
- JWT_SECRET=your_jwt_secret_key_here # Change for production!
|
|
||||||
- JWT_EXPIRATION=24h
|
|
||||||
# Backend is now only accessible through frontend proxy
|
|
||||||
volumes:
|
|
||||||
- sqlite_data:/app/data # SQLite database storage
|
|
||||||
networks:
|
|
||||||
- caddymanager
|
|
||||||
|
|
||||||
# Frontend web UI
|
|
||||||
frontend:
|
|
||||||
image: caddymanager/caddymanager-frontend:latest
|
|
||||||
container_name: caddymanager-frontend
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
environment:
|
|
||||||
- BACKEND_HOST=backend:3000
|
|
||||||
- APP_NAME=Caddy Manager
|
|
||||||
- DARK_MODE=true
|
|
||||||
ports:
|
|
||||||
- "80:80" # Expose web UI
|
|
||||||
networks:
|
|
||||||
- caddymanager
|
|
||||||
|
|
||||||
networks:
|
|
||||||
caddymanager:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
mongodb_data: # Only used when MongoDB profile is active
|
|
||||||
sqlite_data: # SQLite database storage
|
|
||||||
|
|
||||||
# Notes:
|
|
||||||
# - SQLite is the default database engine - no additional setup required!
|
|
||||||
# - To use MongoDB instead, set DB_ENGINE=mongodb and start with: docker-compose --profile mongodb up
|
|
||||||
# - For production, use strong passwords and consider secrets management.
|
|
||||||
# - The backend uses SQLite by default, storing data in a persistent volume.
|
|
||||||
# - The frontend proxies all /api/* requests to the backend service.
|
|
||||||
# - Backend is not directly exposed - all API access goes through the frontend proxy.
|
|
||||||
@ -67,7 +67,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
COMPANY: ${COMPANY}
|
COMPANY: ${COMPANY}
|
||||||
PORT: ${SERVER_PORT:-3002}
|
PORT: ${API_PORT:-3002}
|
||||||
DB_DIALECT: "mysql"
|
DB_DIALECT: "mysql"
|
||||||
DB_HOST: "db"
|
DB_HOST: "db"
|
||||||
DB_PORT: ${DB_PORT}
|
DB_PORT: ${DB_PORT}
|
||||||
@ -79,7 +79,7 @@ services:
|
|||||||
- internal
|
- internal
|
||||||
- edge
|
- edge
|
||||||
ports:
|
ports:
|
||||||
- ${SERVER_PORT:-3002}:${SERVER_PORT:-3002}
|
- ${API_PORT:-3002}:${API_PORT:-3002}
|
||||||
labels:
|
labels:
|
||||||
traefik.enable: "true"
|
traefik.enable: "true"
|
||||||
traefik.http.routers.factuges_rodax_api.rule: Host(`${DOMAIN}`) && PathPrefix(`/api`)
|
traefik.http.routers.factuges_rodax_api.rule: Host(`${DOMAIN}`) && PathPrefix(`/api`)
|
||||||
|
|||||||
@ -73,7 +73,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
COMPANY: ${COMPANY}
|
COMPANY: ${COMPANY}
|
||||||
PORT: ${SERVER_PORT:-3002}
|
PORT: ${API_PORT:-3002}
|
||||||
DB_DIALECT: "mysql"
|
DB_DIALECT: "mysql"
|
||||||
DB_HOST: "db"
|
DB_HOST: "db"
|
||||||
DB_PORT: ${DB_PORT}
|
DB_PORT: ${DB_PORT}
|
||||||
@ -85,7 +85,7 @@ services:
|
|||||||
- internal
|
- internal
|
||||||
- edge
|
- edge
|
||||||
ports:
|
ports:
|
||||||
- ${SERVER_PORT:-3002}:${SERVER_PORT:-3002}
|
- ${API_PORT:-3002}:${API_PORT:-3002}
|
||||||
labels:
|
labels:
|
||||||
traefik.enable: "true"
|
traefik.enable: "true"
|
||||||
# Router
|
# Router
|
||||||
@ -93,7 +93,7 @@ services:
|
|||||||
traefik.http.routers.${COMPANY}-api.entrypoints: websecure
|
traefik.http.routers.${COMPANY}-api.entrypoints: websecure
|
||||||
traefik.http.routers.${COMPANY}-api.tls.certresolver: cfresolver
|
traefik.http.routers.${COMPANY}-api.tls.certresolver: cfresolver
|
||||||
# Servicio
|
# Servicio
|
||||||
traefik.http.services.${COMPANY}-api.loadbalancer.server.port: "${SERVER_PORT:-3002}"
|
traefik.http.services.${COMPANY}-api.loadbalancer.server.port: "${API_PORT:-3002}"
|
||||||
|
|
||||||
# --- Web estática (React compilado por build-factuges.sh) ---
|
# --- Web estática (React compilado por build-factuges.sh) ---
|
||||||
web:
|
web:
|
||||||
|
|||||||
@ -3,7 +3,7 @@ DOMAIN=rodax.factuges.rodax-software.local
|
|||||||
FRONTEND_URL=rodax.factuges.rodax-software.local
|
FRONTEND_URL=rodax.factuges.rodax-software.local
|
||||||
WEB_VERSION=v0.0.4-latest
|
WEB_VERSION=v0.0.4-latest
|
||||||
API_IMAGE=factuges-server:rodax-latest
|
API_IMAGE=factuges-server:rodax-latest
|
||||||
SERVER_PORT=3002
|
API_PORT=3002
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
DB_DIALECT=mysql
|
DB_DIALECT=mysql
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
# Identidad de la compañía
|
||||||
|
COMPANY=rodax
|
||||||
|
|
||||||
|
# Dominios
|
||||||
|
DOMAIN=factuges.rodax-software.local
|
||||||
|
|
||||||
|
# MariaDB
|
||||||
|
DB_ROOT_PASS=verysecret
|
||||||
|
DB_USER=rodax_usr
|
||||||
|
DB_PASS=supersecret
|
||||||
|
DB_NAME=rodax_db
|
||||||
|
DB_PORT=3306
|
||||||
|
|
||||||
|
# API
|
||||||
|
API_PORT=3002
|
||||||
|
API_IMAGE=factuges-server:rodax-latest
|
||||||
|
TEMPLATES_PATH=/repo/apps/server/templates
|
||||||
|
FRONTEND_URL=factuges.rodax-software.local
|
||||||
|
|
||||||
|
|
||||||
|
# SYNC
|
||||||
|
ENV = development
|
||||||
|
LOCAL_TZ = Europe/Madrid
|
||||||
|
STATE_PATH = /app/state
|
||||||
|
SYNC_MODE = all
|
||||||
|
|
||||||
|
FACTUGES_HOST = factuges-pc.rodax-software.local
|
||||||
|
FACTUGES_PORT = 3050
|
||||||
|
FACTUGES_DATABASE = C:\FactuGES\FACTUGES.FDB
|
||||||
|
FACTUGES_USER = sysdba
|
||||||
|
FACTUGES_PASSWORD = masterkey
|
||||||
|
|
||||||
|
FWEB_MYSQL_HOST = db # ${DB_NAME}
|
||||||
|
FWEB_MYSQL_PORT = 3306 # ${DB_PORT}
|
||||||
|
FWEB_MYSQL_DATABASE = factuges_acana # ${DB_NAME}
|
||||||
|
FWEB_MYSQL_USER = acana # ${DB_USER}
|
||||||
|
FWEB_MYSQL_PASSWORD = r@U8%GJ+2e/AWR # ${DB_PASS}
|
||||||
|
|
||||||
|
CTE_COMPANY_ID = '5e4dc5b3-96b9-4968-9490-14bd032fec5f'
|
||||||
|
CTE_SERIE = 'F25'
|
||||||
|
CTE_STATUS_INVOICE = 'issued'
|
||||||
|
CTE_IS_PROFORMA = 0
|
||||||
|
CTE_STATUS_VERIFACTU = 'Pendiente'
|
||||||
|
CTE_LANGUAGE_CODE = 'es'
|
||||||
|
CTE_COUNTRY_CODE = 'es'
|
||||||
|
CTE_IS_COMPANY = 1
|
||||||
|
CTE_SYNC_RESULT_OK = 1
|
||||||
|
CTE_SYNC_RESULT_FAIL = 2
|
||||||
|
|
||||||
|
VERIFACTU_API_KEY = vf_prod_yfjonNPv2E4Fij+5J0hct0zCgUeFYT2dZzb23UZlM+Q=
|
||||||
|
VERIFACTU_BASE_URL = https://api.verifacti.com/
|
||||||
|
VERIFACTU_NIFS_API_KEY = vfn_osYpNdqSzAdTAHpazXG2anz4F3o0gfbSb5FFrCBZcno=
|
||||||
Loading…
Reference in New Issue
Block a user