Initial commit: CF Multisite 멀티테넌트 정적 호스팅
Some checks failed
Deploy to CF Multisite / deploy (push) Failing after 1m53s

- Cloudflare Workers + R2 기반
- Edge 캐싱으로 비용 절감
- 티어별 Rate Limiting (free/basic/pro)
- KV 기반 사용량 추적
- Admin API (usage, customers, tiers, stats)
- Gitea Actions 배포 워크플로우

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-29 09:20:46 +09:00
commit 8850031c45
12 changed files with 4824 additions and 0 deletions

46
sample-site/about.html Normal file
View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>소개 - 데모 사이트</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<a href="/" class="logo">Demo Site</a>
<ul>
<li><a href="/"></a></li>
<li><a href="/about" class="active">소개</a></li>
<li><a href="/contact">연락처</a></li>
</ul>
</nav>
</header>
<main>
<section class="content">
<h1>소개</h1>
<p>이 사이트는 CF Multisite 플랫폼의 데모 사이트입니다.</p>
<h2>기술 스택</h2>
<ul>
<li><strong>Cloudflare Workers</strong> - 엣지에서 실행되는 서버리스 함수</li>
<li><strong>Cloudflare R2</strong> - S3 호환 오브젝트 스토리지</li>
<li><strong>Gitea</strong> - 셀프 호스팅 Git 서버</li>
</ul>
<h2>작동 방식</h2>
<ol>
<li>고객이 Gitea에 정적 파일 업로드</li>
<li>CI/CD가 R2 버킷에 파일 동기화</li>
<li>Workers가 요청을 받아 R2에서 파일 서빙</li>
</ol>
</section>
</main>
<footer>
<p>&copy; 2024 CF Multisite. Powered by Cloudflare.</p>
</footer>
</body>
</html>

37
sample-site/contact.html Normal file
View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>연락처 - 데모 사이트</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<a href="/" class="logo">Demo Site</a>
<ul>
<li><a href="/"></a></li>
<li><a href="/about">소개</a></li>
<li><a href="/contact" class="active">연락처</a></li>
</ul>
</nav>
</header>
<main>
<section class="content">
<h1>연락처</h1>
<p>문의사항이 있으시면 아래로 연락해 주세요.</p>
<div class="contact-info">
<p><strong>이메일:</strong> contact@example.com</p>
<p><strong>GitHub:</strong> github.com/example</p>
</div>
</section>
</main>
<footer>
<p>&copy; 2024 CF Multisite. Powered by Cloudflare.</p>
</footer>
</body>
</html>

47
sample-site/index.html Normal file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>데모 사이트</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<a href="/" class="logo">Demo Site</a>
<ul>
<li><a href="/"></a></li>
<li><a href="/about">소개</a></li>
<li><a href="/contact">연락처</a></li>
</ul>
</nav>
</header>
<main>
<section class="hero">
<h1>CF Multisite에 오신 것을 환영합니다</h1>
<p>Cloudflare Workers + R2로 구동되는 무료 웹 호스팅 서비스입니다.</p>
</section>
<section class="features">
<div class="feature">
<h3>무제한 사이트</h3>
<p>원하는 만큼 사이트를 만들 수 있습니다.</p>
</div>
<div class="feature">
<h3>글로벌 CDN</h3>
<p>전 세계 어디서나 빠른 속도를 제공합니다.</p>
</div>
<div class="feature">
<h3>자동 HTTPS</h3>
<p>SSL 인증서가 자동으로 적용됩니다.</p>
</div>
</section>
</main>
<footer>
<p>&copy; 2024 CF Multisite. Powered by Cloudflare.</p>
</footer>
</body>
</html>

148
sample-site/style.css Normal file
View File

@@ -0,0 +1,148 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color: #333;
background: #f5f5f5;
}
/* Header */
header {
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
nav {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
color: #667eea;
text-decoration: none;
}
nav ul {
display: flex;
list-style: none;
gap: 2rem;
}
nav a {
text-decoration: none;
color: #666;
transition: color 0.2s;
}
nav a:hover,
nav a.active {
color: #667eea;
}
/* Main */
main {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
/* Hero */
.hero {
text-align: center;
padding: 4rem 2rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 16px;
margin-bottom: 2rem;
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.hero p {
font-size: 1.25rem;
opacity: 0.9;
}
/* Features */
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.feature {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.feature h3 {
color: #667eea;
margin-bottom: 0.5rem;
}
/* Content */
.content {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.content h1 {
color: #667eea;
margin-bottom: 1rem;
}
.content h2 {
margin-top: 2rem;
margin-bottom: 0.5rem;
color: #444;
}
.content ul,
.content ol {
margin-left: 1.5rem;
margin-bottom: 1rem;
}
.content li {
margin-bottom: 0.5rem;
}
.contact-info {
margin-top: 2rem;
padding: 1rem;
background: #f9f9f9;
border-radius: 8px;
}
.contact-info p {
margin-bottom: 0.5rem;
}
/* Footer */
footer {
text-align: center;
padding: 2rem;
color: #666;
margin-top: 2rem;
}