Initial commit
This commit is contained in:
126
.woodpecker/build.yaml
Normal file
126
.woodpecker/build.yaml
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# Deploy: build image, push to registry, trigger Portainer stack redeploy.
|
||||||
|
# Runs on push/tag/manual to main only, after ci workflow succeeds.
|
||||||
|
when:
|
||||||
|
- branch: main
|
||||||
|
event: [push, tag, manual]
|
||||||
|
- event: deployment
|
||||||
|
evaluate: 'CI_PIPELINE_DEPLOY_TARGET == "production"'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Docker image build
|
||||||
|
image: docker:latest
|
||||||
|
environment:
|
||||||
|
REGISTRY_REPO: git.mifi.dev/mifi-holdings/mta-sts
|
||||||
|
DOCKER_API_VERSION: '1.43'
|
||||||
|
DOCKER_BUILDKIT: '1'
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- set -e
|
||||||
|
- echo "=== Building Docker image (BuildKit) ==="
|
||||||
|
- 'echo "Commit SHA: ${CI_COMMIT_SHA:0:8}"'
|
||||||
|
- 'echo "Registry repo: $REGISTRY_REPO"'
|
||||||
|
- |
|
||||||
|
build() {
|
||||||
|
docker build \
|
||||||
|
--progress=plain \
|
||||||
|
--tag $REGISTRY_REPO:${CI_COMMIT_SHA} \
|
||||||
|
--tag $REGISTRY_REPO:latest \
|
||||||
|
--label "git.commit=${CI_COMMIT_SHA}" \
|
||||||
|
--label "git.branch=${CI_COMMIT_BRANCH}" \
|
||||||
|
.
|
||||||
|
}
|
||||||
|
for attempt in 1 2 3; do
|
||||||
|
echo "Build attempt $attempt/3"
|
||||||
|
if build; then
|
||||||
|
echo "✓ Docker image built successfully"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Build attempt $attempt failed, retrying in 30s..."
|
||||||
|
sleep 30
|
||||||
|
done
|
||||||
|
echo "All build attempts failed"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Send Docker Image Build Status Notification (success)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Docker image build success 🎉"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Docker image build
|
||||||
|
when:
|
||||||
|
- status: [success]
|
||||||
|
|
||||||
|
- name: Send Docker Image Build Status Notification (failure)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Docker image build failure 💩"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Docker image build
|
||||||
|
when:
|
||||||
|
- status: [failure]
|
||||||
|
|
||||||
|
- name: Push to registry
|
||||||
|
image: docker:latest
|
||||||
|
environment:
|
||||||
|
DOCKER_API_VERSION: '1.43'
|
||||||
|
REGISTRY_URL: git.mifi.dev
|
||||||
|
REGISTRY_REPO: git.mifi.dev/mifi-holdings/mta-sts
|
||||||
|
REGISTRY_USERNAME:
|
||||||
|
from_secret: gitea_registry_username
|
||||||
|
REGISTRY_PASSWORD:
|
||||||
|
from_secret: gitea_package_token
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- set -e
|
||||||
|
- echo "=== Pushing to registry ==="
|
||||||
|
- 'echo "Registry: $REGISTRY_URL"'
|
||||||
|
- 'echo "Repository: $REGISTRY_REPO"'
|
||||||
|
- |
|
||||||
|
echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY_URL" \
|
||||||
|
-u "$REGISTRY_USERNAME" \
|
||||||
|
--password-stdin
|
||||||
|
- docker push $REGISTRY_REPO:${CI_COMMIT_SHA}
|
||||||
|
- docker push $REGISTRY_REPO:latest
|
||||||
|
- echo "✓ Images pushed successfully"
|
||||||
|
depends_on:
|
||||||
|
- Docker image build
|
||||||
|
|
||||||
|
- name: Send Push to Registry Status Notification (success)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Push to registry success 🎉"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Push to registry
|
||||||
|
when:
|
||||||
|
- status: [success]
|
||||||
|
|
||||||
|
- name: Send Push to Registry Status Notification (failure)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Push to registry failure 💩"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Push to registry
|
||||||
|
when:
|
||||||
|
- status: [failure]
|
||||||
59
.woodpecker/deploy.yaml
Normal file
59
.woodpecker/deploy.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Deploy: build image, push to registry, trigger Portainer stack redeploy.
|
||||||
|
# Runs on push/tag/manual to main only, after ci workflow succeeds.
|
||||||
|
when:
|
||||||
|
- branch: main
|
||||||
|
event: [push, tag, manual]
|
||||||
|
- event: deployment
|
||||||
|
evaluate: 'CI_PIPELINE_DEPLOY_TARGET == "production"'
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Trigger Portainer stack redeploy
|
||||||
|
image: curlimages/curl:latest
|
||||||
|
environment:
|
||||||
|
PORTAINER_WEBHOOK_URL:
|
||||||
|
from_secret: portainer_webhook_url
|
||||||
|
commands:
|
||||||
|
- set -e
|
||||||
|
- echo "=== Triggering Portainer stack redeploy ==="
|
||||||
|
- |
|
||||||
|
resp=$(curl -s -w "\n%{http_code}" -X POST "$PORTAINER_WEBHOOK_URL")
|
||||||
|
body=$(echo "$resp" | head -n -1)
|
||||||
|
code=$(echo "$resp" | tail -n 1)
|
||||||
|
if [ "$code" != "200" ] && [ "$code" != "204" ]; then
|
||||||
|
echo "Webhook failed (HTTP $code): $body"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✓ Portainer redeploy triggered (HTTP $code)"
|
||||||
|
depends_on:
|
||||||
|
- Push to registry
|
||||||
|
|
||||||
|
- name: Send Deploy Status Notification (success)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Production Deploy success 🎉"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Trigger Portainer stack redeploy
|
||||||
|
when:
|
||||||
|
- status: [success]
|
||||||
|
|
||||||
|
- name: Send Deploy Status Notification (failure)
|
||||||
|
image: curlimages/curl
|
||||||
|
environment:
|
||||||
|
DISCORD_WEBHOOK_URL:
|
||||||
|
from_secret: discord_webhook_url
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
BODY=$(printf '{"username":"WoodpeckerBot","content":"[%s - Build #%s] Production Deploy failure 💩"}' "$CI_REPO" "$CI_PIPELINE_NUMBER")
|
||||||
|
curl -sS -X POST -H "Content-Type: application/json" -d "$BODY" "$DISCORD_WEBHOOK_URL"
|
||||||
|
depends_on:
|
||||||
|
- Trigger Portainer stack redeploy
|
||||||
|
when:
|
||||||
|
- status: [failure]
|
||||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# Copy nginx configuration
|
||||||
|
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Copy static content
|
||||||
|
COPY html/ /usr/share/nginx/html/
|
||||||
|
|
||||||
|
# Expose port 80
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --retries=3 --start-period=10s \
|
||||||
|
CMD wget --spider -q http://localhost || exit 1
|
||||||
149
docker-compose.yml
Normal file
149
docker-compose.yml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
services:
|
||||||
|
mta-sts:
|
||||||
|
image: git.mifi.dev/mifi-holdings/mta-sts:latest
|
||||||
|
container_name: mta-sts
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--spider", "-q", "http://localhost"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
|
|
||||||
|
# mifi.holdings
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-holdings.rule=Host(`mta-sts.mifi.holdings`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-holdings.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-holdings.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-holdings.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-holdings.service=mta-sts-mifi-holdings"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-holdings.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mifi.com.br
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-com-br.rule=Host(`mta-sts.mifi.com.br`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-com-br.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-com-br.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-com-br.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-com-br.service=mta-sts-mifi-com-br"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-com-br.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mifi.dev
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-dev.rule=Host(`mta-sts.mifi.dev`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-dev.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-dev.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-dev.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-dev.service=mta-sts-mifi-dev"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-dev.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mifi.ventures
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-ventures.rule=Host(`mta-sts.mifi.ventures`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-ventures.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-ventures.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-ventures.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-ventures.service=mta-sts-mifi-ventures"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-ventures.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mifi.vix.br
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-vix-br.rule=Host(`mta-sts.mifi.vix.br`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-vix-br.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-vix-br.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-vix-br.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-vix-br.service=mta-sts-mifi-vix-br"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-vix-br.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mifi.me
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-me.rule=Host(`mta-sts.mifi.me`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-me.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-me.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-me.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mifi-me.service=mta-sts-mifi-me"
|
||||||
|
- "traefik.http.services.mta-sts-mifi-me.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# blackice.vix.br
|
||||||
|
- "traefik.http.routers.mta-sts-blackice-vix-br.rule=Host(`mta-sts.blackice.vix.br`)"
|
||||||
|
- "traefik.http.routers.mta-sts-blackice-vix-br.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-blackice-vix-br.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-blackice-vix-br.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-blackice-vix-br.service=mta-sts-blackice-vix-br"
|
||||||
|
- "traefik.http.services.mta-sts-blackice-vix-br.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# fitz.guru
|
||||||
|
- "traefik.http.routers.mta-sts-fitz-guru.rule=Host(`mta-sts.fitz.guru`)"
|
||||||
|
- "traefik.http.routers.mta-sts-fitz-guru.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-fitz-guru.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-fitz-guru.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-fitz-guru.service=mta-sts-fitz-guru"
|
||||||
|
- "traefik.http.services.mta-sts-fitz-guru.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# umlautpress.com
|
||||||
|
- "traefik.http.routers.mta-sts-umlautpress-com.rule=Host(`mta-sts.umlautpress.com`)"
|
||||||
|
- "traefik.http.routers.mta-sts-umlautpress-com.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-umlautpress-com.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-umlautpress-com.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-umlautpress-com.service=mta-sts-umlautpress-com"
|
||||||
|
- "traefik.http.services.mta-sts-umlautpress-com.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# camilla-rena.com
|
||||||
|
- "traefik.http.routers.mta-sts-camilla-rena-com.rule=Host(`mta-sts.camilla-rena.com`)"
|
||||||
|
- "traefik.http.routers.mta-sts-camilla-rena-com.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-camilla-rena-com.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-camilla-rena-com.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-camilla-rena-com.service=mta-sts-camilla-rena-com"
|
||||||
|
- "traefik.http.services.mta-sts-camilla-rena-com.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# officelift.net
|
||||||
|
- "traefik.http.routers.mta-sts-officelift-net.rule=Host(`mta-sts.officelift.net`)"
|
||||||
|
- "traefik.http.routers.mta-sts-officelift-net.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-officelift-net.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-officelift-net.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-officelift-net.service=mta-sts-officelift-net"
|
||||||
|
- "traefik.http.services.mta-sts-officelift-net.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mylocalpro.biz
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-biz.rule=Host(`mta-sts.mylocalpro.biz`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-biz.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-biz.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-biz.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-biz.service=mta-sts-mylocalpro-biz"
|
||||||
|
- "traefik.http.services.mta-sts-mylocalpro-biz.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# mylocalpro.online
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-online.rule=Host(`mta-sts.mylocalpro.online`)"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-online.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-online.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-online.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-mylocalpro-online.service=mta-sts-mylocalpro-online"
|
||||||
|
- "traefik.http.services.mta-sts-mylocalpro-online.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# happybeardedcarpenter.com
|
||||||
|
- "traefik.http.routers.mta-sts-happybeardedcarpenter-com.rule=Host(`mta-sts.happybeardedcarpenter.com`)"
|
||||||
|
- "traefik.http.routers.mta-sts-happybeardedcarpenter-com.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-happybeardedcarpenter-com.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-happybeardedcarpenter-com.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-happybeardedcarpenter-com.service=mta-sts-happybeardedcarpenter-com"
|
||||||
|
- "traefik.http.services.mta-sts-happybeardedcarpenter-com.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# thenewenglandpalletguy.com
|
||||||
|
- "traefik.http.routers.mta-sts-thenewenglandpalletguy-com.rule=Host(`mta-sts.thenewenglandpalletguy.com`)"
|
||||||
|
- "traefik.http.routers.mta-sts-thenewenglandpalletguy-com.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-thenewenglandpalletguy-com.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-thenewenglandpalletguy-com.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-thenewenglandpalletguy-com.service=mta-sts-thenewenglandpalletguy-com"
|
||||||
|
- "traefik.http.services.mta-sts-thenewenglandpalletguy-com.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# dining-it.com
|
||||||
|
- "traefik.http.routers.mta-sts-dining-it-com.rule=Host(`mta-sts.dining-it.com`)"
|
||||||
|
- "traefik.http.routers.mta-sts-dining-it-com.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.mta-sts-dining-it-com.tls=true"
|
||||||
|
- "traefik.http.routers.mta-sts-dining-it-com.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.mta-sts-dining-it-com.service=mta-sts-dining-it-com"
|
||||||
|
- "traefik.http.services.mta-sts-dining-it-com.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
5
html/.well-known/mta-sts.txt
Normal file
5
html/.well-known/mta-sts.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
version: STSv1
|
||||||
|
mode: enforce
|
||||||
|
mx: mail.mifi.holdings
|
||||||
|
mx: mx02.mail.mifi.holdings
|
||||||
|
max_age: 604800
|
||||||
143
html/index.html
Normal file
143
html/index.html
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>MTA-STS Policy Server</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: white;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||||
|
max-width: 600px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 48px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 64px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% { transform: translateY(0px); }
|
||||||
|
50% { transform: translateY(-10px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #667eea;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-top: 24px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: inline-block;
|
||||||
|
background: #10b981;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #667eea;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.container {
|
||||||
|
padding: 32px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="icon">🔒</div>
|
||||||
|
<h1>MTA-STS Policy Server</h1>
|
||||||
|
<p class="subtitle">
|
||||||
|
This domain serves MTA-STS (Mail Transfer Agent Strict Transport Security) policies to ensure secure email delivery.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="badge">✓ Active & Protected</div>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<h2>What is MTA-STS?</h2>
|
||||||
|
<p>
|
||||||
|
MTA-STS is a security standard that helps protect email in transit by requiring mail servers to use TLS encryption and validate certificates. This prevents downgrade attacks and ensures your emails are delivered securely.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<h2>Policy Location</h2>
|
||||||
|
<p>
|
||||||
|
The MTA-STS policy file is available at:<br>
|
||||||
|
<a href="/.well-known/mta-sts.txt">/.well-known/mta-sts.txt</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
10
nginx/default.conf
Normal file
10
nginx/default.conf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
package.json
Normal file
17
package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "mta-sts",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "MTA-STS static site with nginx",
|
||||||
|
"scripts": {
|
||||||
|
"build": "docker build -t git.mifi.dev/mifi-holdings/mta-sts:latest .",
|
||||||
|
"push": "docker push git.mifi.dev/mifi-holdings/mta-sts:latest",
|
||||||
|
"build:push": "pnpm build && pnpm push"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"mta-sts",
|
||||||
|
"nginx",
|
||||||
|
"docker"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user