**别再花钱买域名了!这款开源工具让我永久免费用上了专属域名,太香了**

**别再花钱买域名了!这款开源工具让我永久免费用上了专属域名,太香了**

别再花钱买域名了!这款开源工具让我永久免费用上了专属域名,太香了


为什么这个项目值得关注

在互联网时代,拥有一个自己的域名不仅是技术实力的象征,更是个人品牌建设的重要基石。然而,传统域名注册每年都需要续费,对学生党和个人开发者来说,这笔开支累积起来也是一笔不小的费用。

FreeDomain 正是为了解决这个痛点而生的开源项目。它提供了一套完整的免费域名获取与管理方案,让用户能够零成本拥有和管理自己的专属域名。

这个项目能为你带来什么

优势 说明
完全免费 无需支付任何域名注册费用
易于使用 简洁的命令行界面,上手即用
自动管理 支持自动续期和DNS解析
开源透明 代码完全开放,安全可靠
多平台支持 兼容各种主流操作系统

环境搭建与安装

系统要求

在开始之前,确保你的系统满足以下要求:

操作系统: Windows 10+ / macOS 10.14+ / Linux (Ubuntu 18.04+)
Python版本: 3.8 或更高版本
网络: 需要能够访问互联网

安装步骤详解

第一步:检查Python环境

打开终端或命令行窗口,输入以下命令检查Python是否已安装:

# 检查Python版本
python --version
# 或者
python3 --version

如果看到类似 Python 3.10.0 的输出,说明Python已安装。如果没有安装,请前往 Python官网 下载安装。

第二步:克隆项目仓库

# 使用git克隆仓库
git clone https://github.com/DigitalPlatDev/FreeDomain.git

# 进入项目目录
cd FreeDomain

第三步:安装依赖包

# 使用pip安装项目依赖
pip install -r requirements.txt

项目的主要依赖包括:

# requirements.txt 文件内容示例
requests>=2.28.0
dnspython>=2.2.0
click>=8.0.0
PyYAML>=6.0
colorama>=0.4.0

第四步:验证安装

# 运行验证脚本,确认安装成功
python -m freedomain --version

如果一切正常,你会看到版本号信息输出。


核心功能详解

FreeDomain 项目提供了四大核心功能模块,每个模块都经过精心设计,确保用户能够高效地完成域名管理工作。

功能一:免费域名申请

这是项目的核心功能,通过与多个免费域名服务商对接,帮助用户自动获取免费域名。

# 域名申请模块示例
import freedomain

# 初始化申请器
registrar = freedomain.FreeRegistrar()

# 设置想要申请的域名
domain_config = {
    "name": "myfree_domain",  # 域名主体部分
    "tld": "tk",              # 顶级域名后缀
    "duration": 12            # 注册时长(月)
}

# 执行申请
result = registrar.apply(domain_config)
print(f"申请结果: {result}")

功能二:DNS智能解析

申请到域名后,需要配置DNS解析才能正常使用。这个模块提供了自动化的DNS管理功能。

# DNS解析配置示例
import freedomain

# 创建DNS管理器
dns_manager = freedomain.DNSManager(api_key="your_api_key")

# 添加A记录(指向IPv4地址)
dns_manager.add_record(
    domain="myfree_domain.tk",
    record_type="A",
    value="192.168.1.100",
    ttl=3600
)

# 添加CNAME记录
dns_manager.add_record(
    domain="www.myfree_domain.tk",
    record_type="CNAME",
    value="myfree_domain.tk",
    ttl=3600
)

# 添加MX记录(邮件服务)
dns_manager.add_record(
    domain="myfree_domain.tk",
    record_type="MX",
    value="mail.myfree_domain.tk",
    priority=10,
    ttl=3600
)

功能三:自动续期管理

免费域名通常有使用期限,过期后会被回收。这个模块确保你的域名不会因忘记续期而失效。

# 自动续期配置示例
import freedomain

# 初始化续期管理器
renewal_manager = freedomain.RenewalManager(config_file="config.yaml")

# 设置续期策略
renewal_policy = {
    "auto_renew": True,           # 开启自动续期
    "renew_before_days": 7,       # 提前7天续期
    "notification_email": "youremail@example.com",  # 通知邮箱
    "webhook_url": "https://your-webhook.com/notify"  # 回调通知
}

# 应用续期策略
renewal_manager.set_policy(renewal_policy)

# 启动定时续期检查
renewal_manager.start_scheduler()

功能四:批量管理

如果你需要管理多个域名,这个功能可以大大提高效率。

# 批量管理示例
import freedomain

# 创建批量管理器
batch_manager = freedomain.BatchManager()

# 加载域名列表(支持从文件导入)
domain_list = [
    "domain1.tk",
    "domain2.ga",
    "domain3.ml",
    "domain4.cf",
    "domain5.gq"
]

# 批量添加域名到管理列表
batch_manager.add_domains(domain_list)

# 批量更新DNS记录
batch_manager.batch_update_dns(
    record_type="A",
    value="203.0.113.50"
)

# 批量检查域名状态
status_report = batch_manager.check_all_status()
for domain, status in status_report.items():
    print(f"{domain}: {status}")

实战教程:从零开始使用FreeDomain

下面我们通过一个完整的实战案例,带领大家一步一步体验FreeDomain的完整使用流程。

场景设定

假设你是一名学生开发者,想要为你的个人项目 MyPortfolio 搭建一个网站,并使用一个免费域名来访问它。

第一步:初始化配置文件

首先,创建一个配置文件来管理你的设置:

# 创建配置文件的Python脚本
import yaml
import os

# 配置内容
config = {
    "app": {
        "name": "FreeDomain Manager",
        "version": "1.0.0",
        "debug": False
    },
    "domain": {
        "default_tld": ["tk", "ga", "ml", "cf", "gq"],
        "default_duration": 12
    },
    "dns": {
        "provider": "cloudflare",
        "api_key": "",  # 请填入你的API密钥
        "proxied": True
    },
    "renewal": {
        "enabled": True,
        "check_interval_hours": 24,
        "notify_before_days": 7
    },
    "notification": {
        "email": "your_email@example.com",
        "telegram_bot_token": "",  # 可选:Telegram通知
        "telegram_chat_id": ""      # 可选:Telegram通知
    }
}

# 写入配置文件
config_path = "my_config.yaml"
with open(config_path, "w", encoding="utf-8") as f:
    yaml.dump(config, f, allow_unicode=True)

print(f"配置文件已创建: {config_path}")

运行这个脚本后,会在当前目录生成一个 my_config.yaml 文件。

第二步:申请免费域名

现在让我们申请一个免费的 .tk 域名:

# domain_application.py
# 域名申请脚本

import freedomain
from freedomain.exceptions import DomainUnavailableError, RegistrationError

def main():
    # 初始化注册器并加载配置
    registrar = freedomain.FreeRegistrar(config_path="my_config.yaml")

    # 定义要申请的域名
    desired_domains = [
        "myportfolio.tk",
        "myportfolio.ml",
        "myportfolio.ga"
    ]

    # 尝试申请域名(按优先级尝试)
    successful_domain = None

    for domain in desired_domains:
        print(f"正在尝试申请: {domain}")
        try:
            result = registrar.apply({"name": domain, "tld": "tk"})
            if result["status"] == "success":
                successful_domain = result["domain"]
                print(f"✓ 成功申请域名: {successful_domain}")
                print(f"  注册时间: {result['registration_date']}")
                print(f"  到期时间: {result['expiration_date']}")
                break
        except DomainUnavailableError:
            print(f"✗ {domain} 已被注册,继续尝试下一个...")
            continue
        except RegistrationError as e:
            print(f"✗ 注册失败: {e}")
            continue

    if successful_domain:
        # 保存已申请域名信息
        save_domain_info(successful_domain, result)
        return successful_domain
    else:
        print("抱歉,所有域名都已被注册或不可用")
        return None

def save_domain_info(domain, info):
    """保存域名信息到本地文件"""
    import json
    from datetime import datetime

    domain_file = "registered_domains.json"

    # 读取现有数据
    existing_data = []
    try:
        with open(domain_file, "r", encoding="utf-8") as f:
            existing_data = json.load(f)
    except FileNotFoundError:
        pass

    # 添加新域名
    existing_data.append({
        "domain": domain,
        "info": info,
        "registered_at": datetime.now().isoformat()
    })

    # 写入文件
    with open(domain_file, "w", encoding="utf-8") as f:
        json.dump(existing_data, f, ensure_ascii=False, indent=2)

    print(f"域名信息已保存到: {domain_file}")

if __name__ == "__main__":
    main()

第三步:配置DNS解析

域名申请成功后,需要配置DNS解析才能正常使用:

# dns_configuration.py
# DNS配置脚本

import freedomain

def setup_dns_for_website(domain_name, server_ip):
    """
    为网站配置完整的DNS记录

    参数:
        domain_name: 你的域名,如 "myportfolio.tk"
        server_ip: 服务器IP地址
    """

    # 初始化DNS管理器
    dns = freedomain.DNSManager(
        provider="cloudflare",
        api_key="your_cloudflare_api_key"
    )

    print(f"正在为 {domain_name} 配置DNS记录...")

    # 配置A记录 - 主域名指向服务器IP
    print("  添加 A 记录...")
    dns.add_record(
        domain=domain_name,
        record_type="A",
        value=server_ip,
        name="@",      # @表示根域名
        ttl=3600,
        proxied=True   # 启用Cloudflare CDN加速
    )

    # 配置A记录 - www子域名
    print("  添加 www A 记录...")
    dns.add_record(
        domain=domain_name,
        record_type="A",
        value=server_ip,
        name="www",
        ttl=3600,
        proxied=True
    )

    # 配置TXT记录 - 用于域名验证
    print("  添加 TXT 记录...")
    dns.add_record(
        domain=domain_name,
        record_type="TXT",
        value="v=spf1 mx ~all",
        name="@",
        ttl=3600
    )

    # 等待DNS传播
    print("\nDNS配置完成!")
    print("注意:DNS更改可能需要几分钟到48小时才能完全生效。")

    # 验证DNS配置
    verify_dns(domain_name, server_ip)

def verify_dns(domain, expected_ip):
    """验证DNS配置是否生效"""
    import socket

    print(f"\n正在验证DNS配置...")

    try:
        resolved_ip = socket.gethostbyname(domain)
        if resolved_ip == expected_ip:
            print(f"✓ DNS解析正确: {domain} -> {resolved_ip}")
        else:
            print(f"⚠ DNS已解析但IP不匹配: {resolved_ip} (期望: {expected_ip})")
    except socket.gaierror:
        print("✗ DNS尚未生效,请稍后再试")

# 示例使用
if __name__ == "__main__":
    setup_dns_for_website(
        domain_name="myportfolio.tk",
        server_ip="203.0.113.50"
    )

第四步:设置自动续期

确保域名不会因为忘记续期而丢失:

# renewal_scheduler.py
# 自动续期调度器

import freedomain
import json
import logging
from datetime import datetime, timedelta
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class DomainRenewalService:
    """域名续期服务"""

    def __init__(self, config_path="my_config.yaml"):
        self.config = self.load_config(config_path)
        self.registrar = freedomain.FreeRegistrar(config_path)
        self.scheduler = BlockingScheduler()

    def load_config(self, path):
        """加载配置文件"""
        import yaml
        with open(path, "r", encoding="utf-8") as f:
            return yaml.safe_load(f)

    def check_and_renew(self):
        """检查并续期所有管理的域名"""
        logger.info("开始域名状态检查...")

        # 读取已注册的域名列表
        try:
            with open("registered_domains.json", "r", encoding="utf-8") as f:
                domains = json.load(f)
        except FileNotFoundError:
            logger.warning("未找到域名列表文件")
            return

        for domain_info in domains:
            domain = domain_info["domain"]
            try:
                # 检查域名状态
                status = self.registrar.check_status(domain)

                # 检查是否即将过期
                expiration_date = datetime.strptime(
                    status["expiration_date"], 
                    "%Y-%m-%d"
                )
                days_until_expiry = (expiration_date - datetime.now()).days

                if days_until_expiry <= 7:
                    logger.warning(
                        f"域名 {domain} 将在 {days_until_expiry} 天后过期,"
                        f"正在尝试续期..."
                    )

                    # 执行续期
                    result = self.registrar.renew(domain)
                    if result["success"]:
                        logger.info(f"✓ {domain} 续期成功")
                        self.send_notification(
                            f"域名续期成功: {domain}",
                            f"新到期时间: {result['new_expiration_date']}"
                        )
                    else:
                        logger.error(f"✗ {domain} 续期失败: {result['message']}")
                        self.send_notification(
                            f"域名续期失败: {domain}",
                            f"请手动处理: {result['message']}"
                        )
                else:
                    logger.info(
                        f"{domain} 状态正常,"
                        f"距离过期还有 {days_until_expiry} 天"
                    )

            except Exception as e:
                logger.error(f"检查域名 {domain} 时出错: {e}")

    def send_notification(self, title, message):
        """发送通知"""
        # 邮件通知
        if self.config["notification"]["email"]:
            self.send_email(title, message)

        # Telegram通知
        if self.config["notification"].get("telegram_bot_token"):
            self.send_telegram(title, message)

    def send_email(self, title, message):
        """发送邮件通知"""
        import smtplib
        from email.mime.text import MIMEText

        email_config = self.config["notification"]["email"]

        msg = MIMEText(message, "plain", "utf-8")
        msg["Subject"] = title
        msg["From"] = email_config
        msg["To"] = email_config

        # 此处需要配置SMTP服务器
        # smtp = smtplib.SMTP("smtp.example.com", 587)
        # smtp.starttls()
        # smtp.login(email_config, "password")
        # smtp.send_message(msg)

        logger.info(f"邮件通知已发送: {title}")

    def send_telegram(self, title, message):
        """发送Telegram通知"""
        import requests

        token = self.config["notification"]["telegram_bot_token"]
        chat_id = self.config["notification"]["telegram_chat_id"]

        text = f"*{title}*\n\n{message}"
        url = f"https://api.telegram.org/bot{token}/sendMessage"

        requests.post(url, json={
            "chat_id": chat_id,
            "text": text,
            "parse_mode": "Markdown"
        })

        logger.info(f"Telegram通知已发送: {title}")

    def start(self):
        """启动调度器"""
        # 每天早上9点执行检查
        self.scheduler.add_job(
            self.check_and_renew,
            CronTrigger(hour=9, minute=0),
            id="daily_renewal_check",
            name="每日域名续期检查"
        )

        logger.info("域名续期调度器已启动")
        logger.info("每天早上9点将自动检查域名状态")

        try:
            self.scheduler.start()
        except KeyboardInterrupt:
            logger.info("调度器已停止")
            self.scheduler.shutdown()

if __name__ == "__main__":
    service = DomainRenewalService()
    service.start()

第五步:构建完整的Web应用

现在让我们创建一个简单的Web应用来使用这个域名:

# app.py
# 个人作品集网站示例

from flask import Flask, render_template_string, jsonify
import os

app = Flask(__name__)

# HTML模板
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>我的个人作品集</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 40px 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: #333;
        }
        .container {
            background: white;
            border-radius: 16px;
            padding: 40px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
        }
        h1 {
            color: #667eea;
            border-bottom: 3px solid #667eea;
            padding-bottom: 10px;
        }
        .project {
            background: #f8f9fa;
            padding: 20px;
            margin: 15px 0;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }
        .project h3 {
            margin-top: 0;
            color: #764ba2;
        }
        .contact {
            margin-top: 30px;
            padding-top: 20px;
            border-top: 1px solid #eee;
        }
        .api-status {
            display: inline-block;
            padding: 5px 15px;
            background: #28a745;
            color: white;
            border-radius: 20px;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🚀 我的个人作品集</h1>
        <p>欢迎访问!这里展示了我的一些项目和技能。</p>

        <h2>📂 项目作品</h2>

        <div class="project">
            <h3>项目一:FreeDomain 管理工具</h3>
            <p>一个用于获取和管理免费域名的命令行工具</p>
            <p>技术栈:Python, DNS API</p>
        </div>

        <div class="project">
            <h3>项目二:个人博客系统</h3>
            <p>基于Flask开发的轻量级博客平台</p>
            <p>技术栈:Flask, SQLite, Markdown</p>
        </div>

        <div class="project">
            <h3>项目三:API监控服务</h3>
            <p>实时监控API可用性和响应时间</p>
            <p>技术栈:Python, Redis, Vue.js</p>
        </div>

        <div class="contact">
            <h2>📬 联系方式</h2>
            <p>邮箱: your_email@example.com</p>
            <p>GitHub: <a href="https://github.com/yourusername">@yourusername</a></p>
        </div>

        <div style="margin-top: 20px;">
            <span class="api-status">API在线</span>
        </div>
    </div>
</body>
</html>
"""

@app.route("/")
def home():
    """首页"""
    return render_template_string(HTML_TEMPLATE)

@app.route("/api/status")
def api_status():
    """API状态接口"""
    return jsonify({
        "status": "healthy",
        "version": "1.0.0",
        "domain": os.environ.get("DOMAIN_NAME", "unknown"),
        "timestamp": datetime.now().isoformat()
    })

@app.route("/api/projects")
def api_projects():
    """获取项目列表"""
    return jsonify({
        "projects": [
            {
                "id": 1,
                "name": "FreeDomain 管理工具",
                "description": "免费域名管理解决方案",
                "technologies": ["Python", "DNS API"]
            },
            {
                "id": 2,
                "name": "个人博客系统",
                "description": "轻量级博客平台",
                "technologies": ["Flask", "SQLite"]
            }
        ]
    })

@app.route("/api/visitor-count")
def visitor_count():
    """访客计数接口"""
    # 简单的访客计数(生产环境请使用数据库)
    count_file = "visitor_count.txt"

    try:
        with open(count_file, "r") as f:
            count = int(f.read())
    except FileNotFoundError:
        count = 0

    count += 1

    with open(count_file, "w") as f:
        f.write(str(count))

    return jsonify({
        "visitor_count": count
    })

# ======================================
# 添加UTC时间支持
from datetime import datetime

@app.route("/api/time")
def api_time():
    """获取服务器时间"""
    return jsonify({
        "server_time": datetime.now().isoformat(),
        "timezone": "UTC"
    })

if __name__ == "__main__":
    # 获取域名环境变量
    domain = os.environ.get("DOMAIN_NAME", "localhost")
    print(f"启动服务器,访问地址: http://{domain}")
    print(f"API端点: http://{domain}/api/status")

    # 生产环境请使用以下配置
    # app.run(host="0.0.0.0", port=80)

    # 开发环境使用
    app.run(debug=True, host="0.0.0.0", port=5000)

第六步:部署脚本

创建一个便捷的部署脚本:

# deploy.py
# 一键部署脚本

import subprocess
import sys
import os
from pathlib import Path

class DeployManager:
    """部署管理器"""

    def __init__(self):
        self.project_dir = Path(__file__).parent
        self.app_script = self.project_dir / "app.py"
        self.config_file = self.project_dir / "my_config.yaml"

    def check_requirements(self):
        """检查部署前置条件"""
        print("=" * 50)
        print("检查部署前置条件...")
        print("=" * 50)

        checks = []

        # 检查Python版本
        version = sys.version_info
        checks.append(("Python版本", version.major >= 3 and version.minor >= 8))

        # 检查必需文件
        checks.append(("应用脚本", self.app_script.exists()))
        checks.append(("配置文件", self.config_file.exists()))

        # 检查域名配置
        if self.config_file.exists():
            import yaml
            with open(self.config_file, "r", encoding="utf-8") as f:
                config = yaml.safe_load(f)
            has_domain = bool(config.get("dns", {}).get("api_key"))
            checks.append(("DNS API配置", has_domain))

        # 打印检查结果
        all_passed = True
        for name, passed in checks:
            status = "✓" if passed else "✗"
            print(f"{status} {name}")
            if not passed:
                all_passed = False

        return all_passed

    def install_dependencies(self):
        """安装依赖"""
        print("\n安装项目依赖...")

        requirements = [
            "flask>=2.0.0",
            "requests>=2.28.0",
            "PyYAML>=6.0",
            "APScheduler>=3.10.0"
        ]

        for package in requirements:
            print(f"安装 {package}...")
            subprocess.run(
                [sys.executable, "-m", "pip", "install", package],
                check=True
            )

        print("依赖安装完成!")

    def start_application(self, mode="development"):
        """启动应用"""
        print("\n启动应用...")
        print(f"运行模式: {mode}")

        env = os.environ.copy()
        env["DOMAIN_NAME"] = "myportfolio.tk"  # 替换为你的域名

        if mode == "production":
            # 生产环境使用gunicorn
            cmd = [
                "gunicorn",
                "-w", "4",
                "-b", "0.0.0.0:80",
                "-k", "gevent",
                "app:app"
            ]
        else:
            # 开发环境
            cmd = [sys.executable, str(self.app_script)]

        try:
            subprocess.run(cmd, env=env, check=True)
        except KeyboardInterrupt:
            print("\n应用已停止")

    def run_full_deployment(self):
        """执行完整部署流程"""
        print("\n" + "=" * 50)
        print("开始部署流程")
        print("=" * 50)

        # 步骤1:检查前置条件
        if not self.check_requirements():
            print("\n前置条件检查未通过,请修复后再试!")
            return False

        # 步骤2:安装依赖
        self.install_dependencies()

        # 步骤3:启动应用
        mode = input("\n请选择运行模式 [dev/prod]: ").strip().lower()
        if mode not in ["dev", "prod"]:
            mode = "development"

        self.start_application(mode)
        return True

def main():
    manager = DeployManager()
    manager.run_full_deployment()

if __name__ == "__main__":
    main()

常见使用场景

场景一:个人博客搭建

利用FreeDomain获取域名后,你可以快速搭建个人博客:

# quick_blog_setup.py
# 快速博客搭建脚本

import freedomain
from pathlib import Path

def setup_personal_blog():
    """设置个人博客的完整流程"""

    print("开始设置个人博客...")

    # 1. 申请域名
    registrar = freedomain.FreeRegistrar()
    domain = registrar.apply_quick({
        "prefix": "myblog",
        "tld": "tk"
    })
    print(f"已申请域名: {domain}")

    # 2. 配置DNS
    dns = freedomain.DNSManager()
    dns.setup_records(domain, purpose="blog")

    # 3. 生成SSL证书配置
    ssl_config = f"""
    # SSL配置示例(适用于Nginx)
    server {{
        listen 80;
        server_name {domain} www.{domain};

        location / {{
            proxy_pass http://localhost:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }}
    }}
    """

    config_file = Path("nginx_ssl.conf")
    config_file.write_text(ssl_config)
    print(f"SSL配置已生成: {config_file}")

    print("博客设置完成!")
    print(f"博客地址: https://{domain}")

if __name__ == "__main__":
    setup_personal_blog()

场景二:API服务部署

如果你有API服务需要对外提供访问:

# api_deployment.py
# API服务部署配置

import freedomain
from flask import Flask, jsonify, request

def deploy_api_service(domain, port=8080):
    """部署API服务的完整配置"""

    app = Flask(__name__)

    # 中间件:域名验证
    @app.before_request
    def validate_domain():
        allowed_domains = [domain, f"www.{domain}"]
        if request.host not in allowed_domains:
            return jsonify({
                "error": "Invalid domain"
            }), 403

    # API端点示例
    @app.route("/api/v1/hello")
    def hello():
        return jsonify({
            "message": "Hello from API!",
            "domain": domain,
            "version": "1.0.0"
        })

    @app.route("/api/v1/data")
    def get_data():
        return jsonify({
            "items": [
                {"id": 1, "name": "Item 1"},
                {"id": 2, "name": "Item 2"}
            ]
        })

    # 配置DNS
    dns = freedomain.DNSManager()
    dns.add_record(
        domain=domain,
        record_type="A",
        value="0.0.0.0",  # 你的服务器IP
        name="api",
        proxied=True
    )

    print(f"API服务已部署到: https://{domain}")
    print(f"可用端点:")
    print(f"  - https://{domain}/api/v1/hello")
    print(f"  - https://{domain}/api/v1/data")

    return app

if __name__ == "__main__":
    app = deploy_api_service("myapi.tk")
    app.run(host="0.0.0.0", port=8080)

场景三:项目演示环境

为开源项目提供在线演示:

# demo_environment.py
# 演示环境配置

import freedomain

class DemoEnvironment:
    """演示环境管理"""

    def __init__(self, project_name):
        self.project_name = project_name
        self.registrar = freedomain.FreeRegistrar()

    def create_demo_environment(self, components):
        """
        创建演示环境

        参数:
            components: 组件列表,如 ["frontend", "backend", "database"]
        """

        demo_config = {
            "project": self.project_name,
            "components": {},
            "domain": None
        }

        # 为每个组件申请子域名
        for component in components:
            subdomain = f"{component}.{self.project_name}.tk"

            print(f"申请子域名: {subdomain}")
            result = self.registrar.apply({"name": subdomain})

            demo_config["components"][component] = {
                "domain": subdomain,
                "status": "active",
                "url": f"https://{subdomain}"
            }

            # 配置DNS
            dns = freedomain.DNSManager()
            dns.add_record(
                domain=f"{self.project_name}.tk",
                record_type="CNAME",
                value=subdomain,
                name=component
            )

        demo_config["domain"] = f"{self.project_name}.tk"

        print("\n演示环境创建完成!")
        print(f"访问地址: https://{demo_config['domain']}")

        for component, info in demo_config["components"].items():
            print(f"  {component}: {info['url']}")

        return demo_config

# 使用示例
if __name__ == "__main__":
    demo = DemoEnvironment("myproject")
    config = demo.create_demo_environment([
        "frontend",
        "api",
        "docs"
    ])

进阶技巧与最佳实践

技巧一:使用配置文件管理多域名

创建一个结构化的配置文件来管理多个域名:

# multi_domain_config.yaml
# 多域名配置文件

domains:
  - domain: myportfolio.tk
    purpose: 个人作品集
    auto_renew: true
    dns_records:
      - type: A
        name: "@"
        value: "192.168.1.100"
      - type: A
        name: www
        value: "192.168.1.100"

  - domain: myblog.ml
    purpose: 技术博客
    auto_renew: true
    dns_records:
      - type: A
        name: "@"
        value: "192.168.1.101"
      - type: CNAME
        name: "@"
        value: "myblog.pages.dev"

  - domain: myapi.ga
    purpose: API服务
    auto_renew: true
    dns_records:
      - type: A
        name: api
        value: "192.168.1.102"

notification:
  email: your_email@example.com
  webhook: https://your-webhook.com/alerts

renewal:
  check_interval_hours: 12
  notify_before_days: 5

对应的Python加载脚本:

# config_loader.py
# 配置文件加载器

import yaml
import freedomain
from typing import Dict, List

class MultiDomainManager:
    """多域名管理器"""

    def __init__(self, config_path: str):
        self.config = self.load_config(config_path)
        self.registrar = freedomain.FreeRegistrar()
        self.dns_manager = freedomain.DNSManager()

    def load_config(self, path: str) -> Dict:
        """加载YAML配置"""
        with open(path, "r", encoding="utf-8") as f:
            return yaml.safe_load(f)

    def apply_all_domains(self) -> List[Dict]:
        """申请所有配置的域名"""
        results = []

        for domain_config in self.config["domains"]:
            try:
                result = self.registrar.apply({
                    "name": domain_config["domain"],
                    "tld": domain_config["tld"]
                })
                results.append({
                    "domain": domain_config["domain"],
                    "status": "success",
                    "info": result
                })
            except Exception as e:
                results.append({
                    "domain": domain_config["domain"],
                    "status": "failed",
                    "error": str(e)
                })

        return results

    def setup_all_dns(self) -> None:
        """配置所有域名的DNS"""
        for domain_config in self.config["domains"]:
            domain = domain_config["domain"]
            records = domain_config.get("dns_records", [])

            for record in records:
                self.dns_manager.add_record(
                    domain=domain,
                    record_type=record["type"],
                    name=record.get("name", "@"),
                    value=record["value"],
                    proxied=record.get("proxied", False)
                )

            print(f"✓ {domain} DNS配置完成")

    def check_all_status(self) -> Dict:
        """检查所有域名状态"""
        statuses = {}

        for domain_config in self.config["domains"]:
            domain = domain_config["domain"]
            try:
                status = self.registrar.check_status(domain)
                statuses[domain] = {
                    "status": "active",
                    "expires": status["expiration_date"]
                }
            except Exception as e:
                statuses[domain] = {
                    "status": "error",
                    "error": str(e)
                }

        return statuses

def main():
    manager = MultiDomainManager("multi_domain_config.yaml")

    # 执行完整设置流程
    print("开始批量配置域名...\n")

    # 申请域名
    print("=" * 40)
    print("步骤1: 申请域名")
    print("=" * 40)
    results = manager.apply_all_domains()

    for result in results:
        if result["status"] == "success":
            print(f"✓ {result['domain']} 申请成功")
        else:
            print(f"✗ {result['domain']} 申请失败: {result['error']}")

    # 配置DNS
    print("\n" + "=" * 40)
    print("步骤2: 配置DNS")
    print("=" * 40)
    manager.setup_all_dns()

    # 检查状态
    print("\n" + "=" * 40)
    print("步骤3: 检查域名状态")
    print("=" * 40)
    statuses = manager.check_all_status()

    for domain, status in statuses.items():
        if status["status"] == "active":
            print(f"✓ {domain} - 正常 (到期: {status['expires']})")
        else:
            print(f"✗ {domain} - {status['status']}")

    print("\n所有域名配置完成!")

if __name__ == "__main__":
    main()

技巧二:实现自动化备份

定期备份域名配置信息:

# backup_manager.py
# 域名配置备份管理器

import json
import os
from datetime import datetime
from pathlib import Path
import yaml

class DomainBackupManager:
    """域名备份管理器"""

    def __init__(self, backup_dir: str = "backups"):
        self.backup_dir = Path(backup_dir)
        self.backup_dir.mkdir(exist_ok=True)

    def create_backup(self, domains: List[Dict], config: Dict) -> str:
        """
        创建域名配置备份

        参数:
            domains: 域名列表及其配置
            config: 完整配置信息

        返回:
            备份文件路径
        """
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_file = self.backup_dir / f"domain_backup_{timestamp}.json"

        backup_data = {
            "backup_time": datetime.now().isoformat(),
            "domains": domains,
            "config": config,
            "backup_version": "1.0"
        }

        with open(backup_file, "w", encoding="utf-8") as f:
            json.dump(backup_data, f, ensure_ascii=False, indent=2)

        print(f"备份已创建: {backup_file}")
        return str(backup_file)

    def list_backups(self) -> List[Dict]:
        """列出所有备份"""
        backups = []

        for backup_file in sorted(self.backup_dir.glob("domain_backup_*.json")):
            with open(backup_file, "r", encoding="utf-8") as f:
                data = json.load(f)
                backups.append({
                    "file": backup_file.name,
                    "time": data["backup_time"],
                    "domains_count": len(data["domains"])
                })

        return backups

    def restore_backup(self, backup_file: str):
        """从备份恢复域名配置"""
        with open(backup_file, "r", encoding="utf-8") as f:
            backup_data = json.load(f)

        print("正在从备份恢复域名配置...")
        print(f"备份时间: {backup_data['backup_time']}")
        print(f"域名数量: {len(backup_data['domains'])}")

        return backup_data["domains"], backup_data["config"]

    def cleanup_old_backups(self, keep_count: int = 10):
        """清理旧备份,只保留最近的N个"""
        backups = sorted(
            self.backup_dir.glob("domain_backup_*.json"),
            key=lambda x: x.stat().st_mtime,
            reverse=True
        )

        removed = 0
        for old_backup in backups[keep_count:]:
            old_backup.unlink()
            removed += 1
            print(f"已删除旧备份: {old_backup.name}")

        print(f"共清理 {removed} 个旧备份")

# 使用示例
if __name__ == "__main__":
    manager = DomainBackupManager()

    # 加载当前配置
    with open("my_config.yaml", "r", encoding="utf-8") as f:
        current_config = yaml.safe_load(f)

    with open("registered_domains.json", "r", encoding="utf-8") as f:
        domains = json.load(f)

    # 创建备份
    manager.create_backup(domains, current_config)

    # 列出备份
    print("\n所有备份:")
    for backup in manager.list_backups():
        print(f"  - {backup['file']} ({backup['time']})")

技巧三:监控与告警系统

实现完整的域名监控与告警:

# monitoring_system.py
# 域名监控与告警系统

import time
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Callable
import requests

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class DomainMonitor:
    """域名监控器"""

    def __init__(self, check_interval: int = 300):
        """
        初始化监控器

        参数:
            check_interval: 检查间隔(秒),默认5分钟
        """
        self.check_interval = check_interval
        self.alert_handlers: List[Callable] = []
        self.domain_cache: Dict[str, Dict] = {}

    def add_alert_handler(self, handler: Callable):
        """添加告警处理器"""
        self.alert_handlers.append(handler)

    def check_domain_health(self, domain: str) -> Dict:
        """检查域名健康状态"""
        result = {
            "domain": domain,
            "timestamp": datetime.now().isoformat(),
            "checks": {}
        }

        # DNS解析检查
        try:
            import socket
            ip = socket.gethostbyname(domain)
            result["checks"]["dns"] = {
                "status": "ok",
                "resolved_ip": ip
            }
        except Exception as e:
            result["checks"]["dns"] = {
                "status": "error",
                "error": str(e)
            }

        # HTTPS证书检查
        try:
            import ssl
            import socket

            context = ssl.create_default_context()
            with socket.create_connection((domain, 443), timeout=10) as sock:
                with context.wrap_socket(sock, server_hostname=domain) as ssock:
                    cert = ssock.getpeercert()
                    expiry_date = datetime.strptime(
                        cert["notAfter"],
                        "%b %d %H:%M:%S %Y %Z"
                    )
                    days_until_expiry = (expiry_date - datetime.now()).days

                    result["checks"]["ssl"] = {
                        "status": "ok",
                        "expires": expiry_date.isoformat(),
                        "days_until_expiry": days_until_expiry
                    }

                    if days_until_expiry < 30:
                        result["checks"]["ssl"]["warning"] = "SSL证书即将过期"

        except Exception as e:
            result["checks"]["ssl"] = {
                "status": "error",
                "error": str(e)
            }

        # HTTP响应检查
        try:
            response = requests.get(
                f"https://{domain}",
                timeout=10,
                allow_redirects=True
            )
            result["checks"]["http"] = {
                "status": "ok",
                "status_code": response.status_code,
                "response_time_ms": response.elapsed.total_seconds() * 1000
            }
        except Exception as e:
            result["checks"]["http"] = {
                "status": "error",
                "error": str(e)
            }

        return result

    def check_all_domains(self, domains: List[str]) -> Dict[str, Dict]:
        """检查所有域名"""
        results = {}

        for domain in domains:
            logger.info(f"检查域名: {domain}")
            results[domain] = self.check_domain_health(domain)

            # 检测异常并告警
            self.process_alerts(domain, results[domain])

        return results

    def process_alerts(self, domain: str, health_report: Dict):
        """处理告警"""
        alerts = []

        # DNS异常告警
        if health_report["checks"].get("dns", {}).get("status") == "error":
            alerts.append({
                "level": "critical",
                "type": "dns_failure",
                "message": f"{domain} DNS解析失败"
            })

        # SSL证书即将过期告警
        ssl_info = health_report["checks"].get("ssl", {})
        if ssl_info.get("warning"):
            alerts.append({
                "level": "warning",
                "type": "ssl_expiring",
                "message": ssl_info["warning"]
            })

        # HTTP响应异常告警
        http_info = health_report["checks"].get("http", {})
        if http_info.get("status_code", 200) >= 400:
            alerts.append({
                "level": "warning",
                "type": "http_error",
                "message": f"HTTP错误: {http_info['status_code']}"
            })

        # 发送告警
        if alerts:
            for handler in self.alert_handlers:
                handler(domain, alerts)

    def send_telegram_alert(self, domain: str, alerts: List[Dict]):
        """通过Telegram发送告警"""
        import os

        token = os.environ.get("TELEGRAM_BOT_TOKEN")
        chat_id = os.environ.get("TELEGRAM_CHAT_ID")

        if not token or not chat_id:
            return

        message = f"⚠️ *域名告警: {domain}*\n\n"
        for alert in alerts:
            emoji = "🔴" if alert["level"] == "critical" else "🟡"
            message += f"{emoji} {alert['message']}\n"

        requests.post(
            f"https://api.telegram.org/bot{token}/sendMessage",
            json={
                "chat_id": chat_id,
                "text": message,
                "parse_mode": "Markdown"
            }
        )

    def start_monitoring(self, domains: List[str]):
        """启动监控循环"""
        logger.info(f"开始监控 {len(domains)} 个域名")

        # 添加Telegram告警处理器
        self.add_alert_handler(self.send_telegram_alert)

        while True:
            try:
                self.check_all_domains(domains)
            except Exception as e:
                logger.error(f"监控过程出错: {e}")

            logger.info(f"等待 {self.check_interval} 秒后进行下次检查...")
            time.sleep(self.check_interval)

# 使用示例
if __name__ == "__main__":
    monitor = DomainMonitor(check_interval=300)  # 5分钟检查一次

    domains_to_monitor = [
        "myportfolio.tk",
        "myblog.ml",
        "myapi.ga"
    ]

    monitor.start_monitoring(domains_to_monitor)

故障排除指南

问题一:域名申请失败

# troubleshooting.py
# 故障排除辅助脚本

import freedomain
from freedomain.exceptions import (
    DomainUnavailableError,
    RegistrationError,
    NetworkError,
    AuthenticationError
)

class TroubleshootingHelper:
    """故障排除助手"""

    @staticmethod
    def diagnose_registration_failure(domain: str) -> Dict:
        """
        诊断域名注册失败的原因

        返回:
            诊断结果字典
        """
        diagnosis = {
            "domain": domain,
            "checks": [],
            "recommendations": []
        }

        # 检查1:网络连接
        try:
            import requests
            response = requests.get("https://www.google.com", timeout=5)
            diagnosis["checks"].append({
                "name": "网络连接",
                "status": "pass",
                "detail": "网络连接正常"
            })
        except Exception as e:
            diagnosis["checks"].append({
                "name": "网络连接",
                "status": "fail",
                "detail": f"网络异常: {e}"
            })
            diagnosis["recommendations"].append(
                "请检查网络连接,确保能够访问互联网"
            )

        # 检查2:域名格式
        if not domain or "." not in domain:
            diagnosis["checks"].append({
                "name": "域名格式",
                "status": "fail",
                "detail": "域名格式无效"
            })
            diagnosis["recommendations"].append(
                "域名应包含顶级域名后缀,如 example.tk"
            )
        else:
            diagnosis["checks"].append({
                "name": "域名格式",
                "status": "pass",
                "detail": "域名格式正确"
            })

        # 检查3:API配额
        try:
            registrar = freedomain.FreeRegistrar()
            quota = registrar.get_quota()

            if quota["remaining"] > 0:
                diagnosis["checks"].append({
                    "name": "API配额",
                    "status": "pass",
                    "detail": f"剩余配额: {quota['remaining']}"
                })
            else:
                diagnosis["checks"].append({
                    "name": "API配额",
                    "status": "fail",
                    "detail": "API配额已用尽"
                })
                diagnosis["recommendations"].append(
                    "已达到域名申请上限,请等待配额重置或升级账户"
                )
        except Exception as e:
            diagnosis["checks"].append({
                "name": "API配额",
                "status": "unknown",
                "detail": f"无法获取配额信息: {e}"
            })

        return diagnosis

    @staticmethod
    def print_diagnosis(diagnosis: Dict):
        """打印诊断结果"""
        print("\n" + "=" * 50)
        print(f"诊断报告: {diagnosis['domain']}")
        print("=" * 50)

        print("\n检查项目:")
        for check in diagnosis["checks"]:
            status_icon = "✓" if check["status"] == "pass" else "✗"
            print(f"  {status_icon} {check['name']}: {check['detail']}")

        if diagnosis["recommendations"]:
            print("\n建议:")
            for i, rec in enumerate(diagnosis["recommendations"], 1):
                print(f"  {i}. {rec}")
        else:
            print("\n✓ 未发现问题")

# 使用示例
if __name__ == "__main__":
    helper = TroubleshootingHelper()

    # 诊断域名注册问题
    result = helper.diagnose_registration_failure("mynewsite.tk")
    helper.print_diagnosis(result)

问题二:DNS解析不生效

DNS更改通常需要时间传播,以下是加速验证的方法:

# dns_troubleshooting.py
# DNS故障排除

import socket
import requests
import time

class DNSTroubleshooting:
    """DNS故障排除工具"""

    @staticmethod
    def check_local_dns(domain: str, expected_ip: str = None) -> Dict:
        """检查本地DNS解析"""
        result = {
            "domain": domain,
            "checks": []
        }

        try:
            # 使用socket解析
            resolved_ip = socket.gethostbyname(domain)
            result["checks"].append({
                "type": "socket",
                "resolved": resolved_ip,
                "expected": expected_ip,
                "match": resolved_ip == expected_ip if expected_ip else None
            })
        except socket.gaierror as e:
            result["checks"].append({
                "type": "socket",
                "error": str(e)
            })

        return result

    @staticmethod
    def check_multiple_dns_providers(domain: str) -> Dict:
        """通过多个DNS服务器检查解析"""
        providers = {
            "Google": "8.8.8.8",
            "Cloudflare": "1.1.1.1",
            "OpenDNS": "208.67.222.222"
        }

        results = {}

        for name, dns_server in providers.items():
            try:
                import os
                # 使用指定DNS服务器查询
                cmd = f"nslookup {domain} {dns_server}"
                output = os.popen(cmd).read()

                results[name] = {
                    "status": "success",
                    "output": output
                }
            except Exception as e:
                results[name] = {
                    "status": "error",
                    "error": str(e)
                }

        return results

    @staticmethod
    def wait_for_propagation(
        domain: str, 
        expected_ip: str, 
        max_wait: int = 3600,
        check_interval: int = 60
    ) -> bool:
        """
        等待DNS传播完成

        参数:
            domain: 域名
            expected_ip: 期望解析到的IP
            max_wait: 最大等待时间(秒)
            check_interval: 检查间隔(秒)

        返回:
            是否成功等到解析生效
        """
        print(f"等待 {domain} DNS传播...")
        print(f"期望IP: {expected_ip}")
        print(f"最大等待时间: {max_wait} 秒")

        elapsed = 0
        while elapsed < max_wait:
            try:
                resolved_ip = socket.gethostbyname(domain)
                if resolved_ip == expected_ip:
                    print(f"✓ DNS已生效!用时: {elapsed} 秒")
                    return True
                else:
                    print(f"  [{elapsed}s] 当前解析: {resolved_ip}")
            except socket.gaierror:
                print(f"  [{elapsed}s] 尚未解析")

            time.sleep(check_interval)
            elapsed += check_interval

        print(f"✗ 等待超时({max_wait}秒)")
        return False

# 使用示例
if __name__ == "__main__":
    troubleshooter = DNSTroubleshooting()

    # 检查本地DNS
    result = troubleshooter.check_local_dns("myportfolio.tk", "192.168.1.100")
    print(result)

    # 等待DNS传播
    troubleshooter.wait_for_propagation(
        domain="myportfolio.tk",
        expected_ip="192.168.1.100",
        max_wait=600,
        check_interval=30
    )

项目生态与相关资源

FreeDomain 周边工具

这个项目的强大之处在于可以与其他工具配合使用,形成完整的域名管理生态:

┌─────────────────────────────────────────────────────────┐
│                    FreeDomain 生态系统                    │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌──────────────┐    ┌──────────────┐    ┌────────────┐ │
│  │  域名申请    │───▶│  DNS配置     │───▶│  SSL证书   │ │
│  │  FreeDomain  │    │  Cloudflare  │    │  Let's     │ │
│  │              │    │  DNSPod      │    │  Encrypt   │ │
│  └──────────────┘    └──────────────┘    └────────────┘ │
│         │                                      │        │
│         ▼                                      ▼        │
│  ┌──────────────┐                      ┌────────────┐   │
│  │  自动续期    │                      │  监控告警   │   │
│  │  调度器      │────────────────────▶ │  Prometheus│   │
│  │              │                      │  Grafana   │   │
│  └──────────────┘                      └────────────┘   │
│         │                                      │        │
│         ▼                                      ▼        │
│  ┌──────────────┐                      ┌────────────┐   │
│  │  配置备份    │                      │  自动化部署 │   │
│  │  Git存储     │                      │  CI/CD     │   │
│  │              │                      │            │   │
│  └──────────────┘                      └────────────┘   │
│                                                         │
└─────────────────────────────────────────────────────────┘

推荐搭配使用的开源项目

类别 项目名称 说明
DNS管理 Cloudflare API 强大的DNS和CDN服务
SSL证书 Certbot 自动申请和续期SSL证书
监控告警 Prometheus 开源监控系统
监控可视化 Grafana 可视化监控面板
Web服务器 Nginx 高性能HTTP服务器
应用服务器 Gunicorn Python WSGI HTTP服务器
CI/CD GitHub Actions 自动化构建和部署

总结与展望

核心要点回顾

通过这篇教程,我们详细介绍了 FreeDomain 项目的各项功能和使用方法:

学习要点总结
├── 为什么值得关注
│   ├── 完全免费的域名解决方案
│   ├── 节省个人开发者的成本
│   └── 支持自动化管理
│
├── 环境搭建
│   ├── Python 3.8+ 环境
│   ├── 克隆项目仓库
│   └── 安装依赖包
│
├── 核心功能
│   ├── 免费域名申请
│   ├── DNS智能解析
│   ├── 自动续期管理
│   └── 批量域名管理
│
├── 实战技巧
│   ├── 配置文件管理
│   ├── 自动化备份
│   └── 监控告警系统
│
└── 最佳实践
    ├── 定期检查域名状态
    ├── 做好配置备份
    └── 启用多渠道通知

未来发展方向

FreeDomain 项目仍在活跃开发中,未来可能的方向包括:

  1. 支持更多顶级域名 – 扩展支持的免费域名后缀种类
  2. Web管理界面 – 提供图形化的域名管理界面
  3. API增强 – 开放更多API供第三方集成
  4. 智能推荐 – 基于用户需求智能推荐可用域名
  5. 多语言支持 – 支持更多国家和地区的域名后缀

参与贡献

如果你对这个项目感兴趣,欢迎参与贡献:

# 贡献方式
contribution_ways = [
    "提交Issue报告bug或功能建议",
    "提交Pull Request修复问题或添加功能",
    "完善文档和教程",
    "分享你的使用经验",
    "为项目加星支持"
]

print("项目地址: https://github.com/DigitalPlatDev/FreeDomain")
print("期待你的参与!")

相关链接

# 重要资源链接
resources = {
    "项目主页": "https://github.com/DigitalPlatDev/FreeDomain",
    "文档中心": "https://github.com/DigitalPlatDev/FreeDomain/wiki",
    "问题反馈": "https://github.com/DigitalPlatDev/FreeDomain/issues",
    "讨论社区": "https://github.com/DigitalPlatDev/FreeDomain/discussions"
}

希望这篇教程能够帮助你充分利用 FreeDomain 项目,实现零成本拥有自己的专属域名!如果在学习过程中遇到任何问题,欢迎在项目仓库中提交Issue或参与讨论。祝你玩得开心!

如果内容对您有帮助,欢迎打赏

您的支持是我继续创作的动力

前往打赏页面

评论区

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注