-
Documentation •
-
Chat on Matrix •
-
GitHub
+
+
+
+
+
See It In Action
+
Write infrastructure automation in pure Python. No YAML, no DSL, just clean, readable Python code.
+
+
+
+
+
+from pyinfra.operations import apt, systemd
+
+apt.packages(
+ name="Install nginx",
+ packages=["nginx"],
+)
+
+
+systemd.service(
+ name="Restart and enable the nginx service",
+ service="nginx.service",
+ running=True,
+ restarted=True,
+ enabled=True,
+)
+
+
+
+
Simple, Powerful, Pythonic
+
+ - No new syntax to learn — If you know Python, you know pyinfra
+ - Full Python capabilities — Use loops, conditions, functions, and any Python library
+ - Type hints & IDE support — Get autocomplete and inline documentation
+ - Instant feedback — See exactly what commands run on your servers in real-time
+
+
+
+
+
+
+
+
+
+
Perfect For Any Infrastructure Task
+
+
+
🖥️
+
Server Provisioning
+
Set up and configure new servers from bare metal to production-ready. Install packages, configure services, and manage users with idempotent operations.
+
+
+
🔄
+
Application Deployment
+
Deploy applications across your fleet with rolling updates, health checks, and automatic rollbacks. Perfect for web apps, microservices, and batch jobs.
+
+
+
⚙️
+
Configuration Management
+
Keep your infrastructure in sync with declarative configuration. Detect and fix drift automatically with diff checking and change tracking.
+
+
+
🔧
+
Ad-hoc Automation
+
Run one-off commands across hundreds of servers. Gather system information, perform updates, or execute maintenance tasks instantly.
+
+
+
🐳
+
Container Orchestration
+
Manage Docker containers and images. Deploy containers, configure networks, and handle volumes across your container infrastructure.
+
+
+
☁️
+
Cloud Infrastructure
+
Integrate with cloud providers and tools like Terraform. Pull dynamic inventory and automate cloud resource configuration seamlessly.
+
+
+
+
+
+
+
+
+
How pyinfra Compares
+
+
+
+
+ | Feature |
+ pyinfra |
+ Ansible |
+
+
+
+
+ | Language |
+ ✓ Pure Python |
+ YAML + Jinja2 |
+
+
+ | Speed |
+ ✓ 10x faster |
+ Slower execution |
+
+
+ | Agent Required |
+ ✓ No |
+ ✓ No |
+
+
+ | Real-time Output |
+ ✓ Yes |
+ Limited |
+
+
+ | Idempotent Operations |
+ ✓ Built-in |
+ ✓ Built-in |
+
+
+ | Target Systems |
+ ✓ SSH, Docker, Local |
+ SSH, WinRM |
+
+
+ | Learning Curve |
+ ✓ Low (if you know Python) |
+ Medium |
+
+
+ | Extensibility |
+ ✓ Full Python ecosystem |
+ Limited to modules |
+
+
+
+
+
+
+
+
+
+
+
Frequently Asked Questions
+
+
+
Is pyinfra production-ready?
+
Yes! pyinfra is battle-tested and used by companies worldwide to manage production infrastructure. It has a stable API and comprehensive test coverage.
+
+
+
Can I migrate from Ansible?
+
Absolutely. Many teams have successfully migrated from Ansible to pyinfra. The concepts are similar, but the Python-based approach offers more flexibility and better performance.
+
+
+
Does it work with Windows?
+
pyinfra targets POSIX-compatible systems. While you can run pyinfra from Windows (via WSL), target systems should be Linux, macOS, or Unix-based systems.
+
+
+
How does it handle secrets?
+
pyinfra integrates with popular secret management tools. You can use environment variables, encrypted files, or integrate with HashiCorp Vault, AWS Secrets Manager, etc.
+
+
+
Can I use existing Python packages?
+
Yes! That's one of pyinfra's biggest advantages. You can import and use any Python package in your deployment scripts, from requests to boto3 to custom libraries.
+
+
+
What's the performance overhead?
+
Minimal. pyinfra uses efficient SSH multiplexing and parallel execution. It can manage thousands of servers simultaneously with low resource usage and predictable performance.
+
+
+
+
+
+
+
+
+
-
+
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 0000000..893f4c1
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,5 @@
+# robots.txt for pyinfra.com
+
+User-agent: *
+Allow: /
+
diff --git a/static/pyinfra.css b/static/pyinfra.css
index 63d4708..3905d8e 100644
--- a/static/pyinfra.css
+++ b/static/pyinfra.css
@@ -10,6 +10,21 @@
body {
min-width: 0;
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ background-attachment: fixed;
+}
+
+/* Visually hidden but accessible to screen readers */
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
}
a:hover {
@@ -19,20 +34,26 @@ a:hover {
header {
padding: 30px 0 20px 0;
+ background: rgba(255, 255, 255, 0.8);
+ backdrop-filter: blur(10px);
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
-h1 {
+.logo-wrapper {
width: auto;
display: inline-block;
- margin-top: -16px;
- font-family: 'Roboto Slab', serif;
- font-weight: 500;
margin-bottom: 0;
+ transition: transform 0.3s ease;
}
-h1 img {
- float: left;
- margin-top: -5px;
- margin-right: 5px;
+
+.logo-wrapper:hover {
+ transform: scale(1.02);
+}
+
+.logo-wrapper img {
+ display: block;
+ max-width: 100%;
+ height: auto;
}
.container {
@@ -65,6 +86,41 @@ h2 {
font-weight: 500;
}
+.features-heading {
+ text-align: center;
+ font-size: 32px;
+ margin-bottom: 30px;
+ color: #2c3e50;
+ position: relative;
+ padding-bottom: 15px;
+}
+
+.features-heading::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 80px;
+ height: 4px;
+ background: linear-gradient(90deg, rgb(96, 205, 110), rgb(74, 163, 84));
+ border-radius: 2px;
+}
+
+.hero-text {
+ line-height: 1.6;
+ color: #2c3e50;
+}
+
+.comparison-text {
+ color: #34495e;
+ margin-top: 20px;
+ padding: 20px;
+ background: rgba(96, 205, 110, 0.1);
+ border-left: 4px solid rgb(96, 205, 110);
+ border-radius: 4px;
+}
+
ul.features {
display: flex;
flex-wrap: wrap;
@@ -76,17 +132,31 @@ ul.features li {
width: 48%;
list-style: none;
margin-bottom: 20px;
- padding: 20px;
- background: #F7F7F7;
- border-radius: 4px;
+ padding: 25px;
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ transition: all 0.3s ease;
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+ul.features li:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
+ border-color: rgba(96, 205, 110, 0.3);
}
ul.features li i {
font-style: normal;
display: inline-block;
+ font-size: 24px;
+ margin-right: 8px;
}
ul.features li:hover i {
animation: icon-rotate 3s infinite linear;
}
+ul.features li strong {
+ color: #2c3e50;
+ font-size: 19px;
+}
@keyframes icon-rotate {
0% {
@@ -121,13 +191,356 @@ p.big {
font-size: 18px;
}
+.section-intro {
+ text-align: center;
+ font-size: 18px;
+ color: #555;
+ margin-bottom: 40px;
+ max-width: 700px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/* Stats Grid */
+.stats-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 20px;
+ margin: 40px 0;
+}
+
+.stat-item {
+ text-align: center;
+ padding: 30px 20px;
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ border-radius: 12px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ transition: all 0.3s ease;
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.stat-item:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
+}
+
+.stat-number {
+ font-size: 48px;
+ font-weight: 700;
+ font-family: 'Roboto Slab', serif;
+ color: rgb(74, 163, 84);
+ line-height: 1;
+ margin-bottom: 10px;
+}
+
+.stat-label {
+ font-size: 14px;
+ color: #666;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+/* Code Example Section */
+.code-example-section {
+ margin: 60px 0;
+}
+
+.code-example-wrapper {
+ display: grid;
+ grid-template-columns: 1.2fr 1fr;
+ gap: 50px;
+ align-items: start;
+ margin-top: 30px;
+}
+
+.code-example {
+ background: #1e1e1e;
+ border-radius: 8px;
+ overflow: hidden;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
+}
+
+.code-header {
+ background: #2d2d2d;
+ padding: 12px 20px;
+ border-bottom: 1px solid #404040;
+}
+
+.code-file {
+ color: #aaa;
+ font-size: 13px;
+ font-family: 'Monaco', 'Menlo', monospace;
+}
+
+.code-example pre {
+ margin: 0;
+ padding: 20px;
+ overflow-x: auto;
+}
+
+.code-example code {
+ font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
+ font-size: 14px;
+ line-height: 1.6;
+ color: #d4d4d4;
+}
+
+.code-comment {
+ color: #6a9955;
+}
+
+.code-keyword {
+ color: #569cd6;
+}
+
+.code-string {
+ color: #ce9178;
+}
+
+.code-benefits h3 {
+ font-family: 'Roboto Slab', serif;
+ font-size: 24px;
+ color: #2c3e50;
+ margin-bottom: 20px;
+}
+
+.code-benefits ul {
+ list-style: none;
+ padding: 0;
+}
+
+.code-benefits li {
+ padding: 12px 0;
+ border-bottom: 1px solid #e0e0e0;
+ color: #555;
+ line-height: 1.6;
+}
+
+.code-benefits li:last-child {
+ border-bottom: none;
+}
+
+/* Use Cases Section */
+.use-cases-section {
+ margin: 80px 0;
+}
+
+.use-cases-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 30px;
+ margin-top: 40px;
+}
+
+.use-case-card {
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ padding: 35px;
+ border-radius: 12px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ transition: all 0.3s ease;
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.use-case-card:hover {
+ transform: translateY(-8px);
+ box-shadow: 0 12px 25px rgba(0, 0, 0, 0.12);
+ border-color: rgba(96, 205, 110, 0.3);
+}
+
+.use-case-icon {
+ font-size: 48px;
+ margin-bottom: 20px;
+}
+
+.use-case-card h3 {
+ font-family: 'Roboto Slab', serif;
+ font-size: 22px;
+ color: #2c3e50;
+ margin-bottom: 15px;
+}
+
+.use-case-card p {
+ color: #555;
+ line-height: 1.7;
+ font-size: 16px;
+}
+
+/* Comparison Table */
+.comparison-section {
+ margin: 80px 0;
+}
+
+.comparison-table-wrapper {
+ overflow-x: auto;
+ margin-top: 40px;
+}
+
+.comparison-table {
+ width: 100%;
+ border-collapse: collapse;
+ background: white;
+ border-radius: 8px;
+ overflow: hidden;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+}
+
+.comparison-table thead {
+ background: linear-gradient(135deg, rgb(96, 205, 110), rgb(74, 163, 84));
+}
+
+.comparison-table th {
+ padding: 18px 20px;
+ text-align: left;
+ color: white;
+ font-family: 'Roboto Slab', serif;
+ font-weight: 500;
+ font-size: 16px;
+}
+
+.comparison-table td {
+ padding: 16px 20px;
+ border-bottom: 1px solid #e0e0e0;
+ color: #555;
+ font-size: 15px;
+}
+
+.comparison-table tbody tr:last-child td {
+ border-bottom: none;
+}
+
+.comparison-table tbody tr:hover {
+ background: #f8f9fa;
+}
+
+.comparison-table td:first-child {
+ font-weight: 600;
+ color: #2c3e50;
+}
+
+.comparison-table .check {
+ color: rgb(74, 163, 84);
+ font-weight: bold;
+ margin-right: 5px;
+}
+
+/* FAQ Section */
+.faq-section {
+ margin: 80px 0;
+}
+
+.faq-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 30px;
+ margin-top: 40px;
+}
+
+.faq-item {
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ padding: 30px;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ border-left: 4px solid rgb(96, 205, 110);
+ transition: all 0.3s ease;
+}
+
+.faq-item:hover {
+ box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
+ transform: translateX(5px);
+}
+
+.faq-item h3 {
+ font-family: 'Roboto Slab', serif;
+ font-size: 18px;
+ color: #2c3e50;
+ margin-bottom: 12px;
+}
+
+.faq-item p {
+ color: #555;
+ line-height: 1.7;
+ font-size: 15px;
+ margin: 0;
+}
+
+/* Community Section */
+.community-section {
+ margin: 80px 0;
+}
+
+.community-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 30px;
+ margin-top: 40px;
+}
+
+.community-card {
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+ padding: 40px 30px;
+ border-radius: 12px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ text-align: center;
+ transition: all 0.3s ease;
+ border: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.community-card:hover {
+ transform: translateY(-8px);
+ box-shadow: 0 12px 25px rgba(0, 0, 0, 0.12);
+ border-color: rgba(96, 205, 110, 0.3);
+}
+
+.community-icon {
+ font-size: 56px;
+ margin-bottom: 20px;
+}
+
+.community-card h3 {
+ font-family: 'Roboto Slab', serif;
+ font-size: 22px;
+ color: #2c3e50;
+ margin-bottom: 15px;
+}
+
+.community-card p {
+ color: #555;
+ line-height: 1.7;
+ font-size: 15px;
+ margin-bottom: 20px;
+}
+
+.community-link {
+ display: inline-block;
+ color: rgb(74, 163, 84);
+ font-weight: 700;
+ text-decoration: none;
+ font-size: 16px;
+ transition: all 0.3s ease;
+}
+
+.community-link:hover {
+ color: rgb(62, 142, 72);
+ transform: translateX(5px);
+}
+
footer {
- padding: 60px 0 10px 0;
+ padding: 60px 0 30px 0;
+ background: rgba(255, 255, 255, 0.6);
+ margin-top: 60px;
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
}
footer div.container {
display: flex;
flex-wrap: wrap;
- justify-content: space-between;
+ justify-content: center;
+ text-align: center;
+}
+footer .footer-text {
+ color: #666;
+ font-size: 15px;
+ line-height: 1.6;
}
footer ul {
font-size: 16px;
@@ -177,19 +590,36 @@ div.buttons a.button {
font-size: 40px;
font-family: 'Roboto Slab', serif;
font-weight: 400;
- background: rgb(96, 205, 110);
- box-shadow: 5px 5px 0 rgb(74, 163, 84);
- border-radius: 4px;
+ background: linear-gradient(135deg, rgb(96, 205, 110), rgb(74, 163, 84));
+ box-shadow: 5px 5px 0 rgb(74, 163, 84), 0 10px 25px rgba(96, 205, 110, 0.2);
+ border-radius: 8px;
padding: 20px;
color: white;
text-decoration: none;
margin: 0;
display: block;
width: 48%;
+ transition: all 0.3s ease;
+ position: relative;
+ overflow: hidden;
+}
+div.buttons a.button::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.1);
+ transition: left 0.5s ease;
+}
+div.buttons a.button:hover::before {
+ left: 100%;
}
div.buttons a.button:hover {
- background: rgb(74, 163, 84);
- box-shadow: 7px 7px 0 rgb(62, 142, 72);
+ background: linear-gradient(135deg, rgb(74, 163, 84), rgb(62, 142, 72));
+ box-shadow: 7px 7px 0 rgb(62, 142, 72), 0 15px 35px rgba(96, 205, 110, 0.3);
+ transform: translateY(-2px);
cursor: pointer;
}
@@ -207,5 +637,102 @@ div.buttons a.button:hover {
div.buttons a.button {
width: 100%;
margin-bottom: 20px;
+ font-size: 32px;
+ }
+
+ /* Stats Grid Mobile */
+ .stats-grid {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 15px;
+ margin: 30px 0;
+ }
+
+ .stat-item {
+ padding: 20px 15px;
+ }
+
+ .stat-number {
+ font-size: 36px;
+ }
+
+ .stat-label {
+ font-size: 12px;
+ }
+
+ /* Code Example Mobile */
+ .code-example-wrapper {
+ grid-template-columns: 1fr;
+ gap: 30px;
+ }
+
+ .code-example-section {
+ margin: 40px 0;
+ }
+
+ .code-example code {
+ font-size: 12px;
+ }
+
+ /* Use Cases Mobile */
+ .use-cases-grid {
+ grid-template-columns: 1fr;
+ gap: 20px;
+ }
+
+ .use-case-card {
+ padding: 25px;
+ }
+
+ /* Comparison Table Mobile */
+ .comparison-table {
+ font-size: 13px;
+ }
+
+ .comparison-table th,
+ .comparison-table td {
+ padding: 12px 10px;
+ }
+
+ /* FAQ Mobile */
+ .faq-grid {
+ grid-template-columns: 1fr;
+ gap: 20px;
+ }
+
+ /* Community Mobile */
+ .community-grid {
+ grid-template-columns: 1fr;
+ gap: 20px;
+ }
+
+ .community-card {
+ padding: 30px 20px;
+ }
+
+ .features-heading {
+ font-size: 26px;
+ }
+
+ .section-intro {
+ font-size: 16px;
+ }
+}
+
+/* Tablet Styles */
+@media all and (min-width: 769px) and (max-width: 1024px) {
+ .use-cases-grid {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .stats-grid {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .code-example-wrapper {
+ gap: 25px;
+ }
+
+ .community-grid {
+ grid-template-columns: repeat(2, 1fr);
}
}