Initial commit: NX9 philosophy, architecture, roadmap and website
No files matched your search
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/nx9.iml" filepath="$PROJECT_DIR$/.idea/nx9.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="EMPTY_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,108 @@
|
||||
# NX9 Architecture
|
||||
|
||||
## A Philosophy-Driven Ecosystem for Self-Hosted Infrastructure
|
||||
|
||||
**NX9** is an ecosystem of independent, philosophically aligned infrastructure software built by Sunil Thakare (@thakares).
|
||||
|
||||
Every project is designed around one simple idea:
|
||||
|
||||
> **Infrastructure should belong to its operator — not to a cloud provider, subscription service, or vendor.**
|
||||
|
||||
NX9 is not a framework.
|
||||
It is not a platform that requires dozens of services.
|
||||
It is not a cloud product that happens to support self-hosting.
|
||||
|
||||
Instead, NX9 is a collection of carefully engineered **single-binary Rust applications** that prioritize:
|
||||
|
||||
- Privacy
|
||||
- Simplicity
|
||||
- Reliability
|
||||
- Performance
|
||||
- Operational Excellence
|
||||
- Long-term Maintainability
|
||||
|
||||
Every application is fully open-source, Linux-native, resource-efficient, and designed to run equally well on Raspberry Pi, mini PCs, VPS instances, enterprise servers, air-gapped government infrastructure, or personal homelabs.
|
||||
|
||||
**No telemetry. No vendor lock-in. No mandatory cloud. No unnecessary complexity.**
|
||||
|
||||
---
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
The NX9 ecosystem follows several consistent principles across every project.
|
||||
|
||||
### 1. Operator Ownership
|
||||
|
||||
The operator owns the binaries, the configuration, the databases, the backups, the encryption keys, and the deployment.
|
||||
|
||||
No service depends on proprietary APIs or cloud-hosted control planes.
|
||||
|
||||
### 2. Self-Hosting First
|
||||
|
||||
Every architectural decision begins with one question:
|
||||
|
||||
> "Can this be deployed and operated by a single administrator?"
|
||||
|
||||
If the answer requires Kubernetes, managed databases, cloud messaging, or external dependencies, the design is reconsidered.
|
||||
|
||||
### 3. Simplicity Over Complexity
|
||||
|
||||
NX9 intentionally avoids fashionable complexity. Instead of dozens of microservices, service meshes, or distributed databases, NX9 prefers:
|
||||
|
||||
- One binary
|
||||
- One configuration
|
||||
- One (or a few) SQLite databases
|
||||
- One administrator
|
||||
|
||||
Simple systems are easier to understand, secure, and recover.
|
||||
|
||||
### 4. Privacy by Default
|
||||
|
||||
Privacy is a design requirement, not an optional feature. Applications never assume cloud connectivity, analytics collection, or third-party tracking.
|
||||
|
||||
### 5. Security by Design
|
||||
|
||||
Security is embedded throughout the stack:
|
||||
|
||||
- Argon2id password hashing
|
||||
- Ed25519 signatures
|
||||
- BLAKE3 hashing
|
||||
- RBAC
|
||||
- CSRF protection
|
||||
- Secure cookies
|
||||
- Transaction-safe audit logs
|
||||
- Hardened compilation flags
|
||||
|
||||
### 6. Operational Excellence
|
||||
|
||||
Every project includes:
|
||||
|
||||
- Diagnostics and health checks
|
||||
- Backup and restore procedures
|
||||
- Migration tools
|
||||
- CLI administration
|
||||
- Reproducible deployments
|
||||
- Structured logging
|
||||
- Documentation
|
||||
|
||||
### 7. Long-Term Stability
|
||||
|
||||
NX9 intentionally avoids dependency churn. Projects are expected to remain understandable and maintainable years into the future.
|
||||
|
||||
---
|
||||
|
||||
## Core Architectural Pillars
|
||||
|
||||
### 1. Pure Rust
|
||||
|
||||
All projects are implemented in modern Rust (2021 Edition) for memory safety, predictable performance, and minimal runtime overhead. Typical binaries are around 10–12 MB.
|
||||
|
||||
### 2. Single Binary Deployment
|
||||
|
||||
One executable contains the HTTP server, business logic, authentication, database migrations, CLI, and templates.
|
||||
|
||||
Installation is often as simple as:
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
./application serve
|
||||
@@ -0,0 +1,466 @@
|
||||
# NX9 Philosophy: Engineering Beyond Frameworks
|
||||
|
||||
## A Real-World Case Study in Software Minimalism, Explicit Routing, and Reduced Attack Surface
|
||||
|
||||
> *"The best way to reduce complexity is not to manage more software—it is to deploy less software."*
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This case study examines the first publicly accessible deployment of **NX9** and the unsolicited Internet traffic it received immediately after exposure.
|
||||
|
||||
The objective was not to conduct a penetration test or security benchmark. Instead, the production access logs were analyzed to understand how real-world Internet scanners interacted with a deliberately minimal software stack.
|
||||
|
||||
The results were revealing.
|
||||
|
||||
During the observed period:
|
||||
|
||||
* **362 HTTP requests** were received.
|
||||
* **331 requests (91.4%)** resulted in **`404 Not Found`**.
|
||||
* **20 requests (5.5%)** returned **`304 Not Modified`**, indicating normal browser caching.
|
||||
* **11 requests (3.1%)** returned **`200 OK`**, serving legitimate published resources.
|
||||
|
||||
The overwhelming majority of incoming requests were **not attempts to use the application**.
|
||||
|
||||
They were attempts to identify technologies that were never deployed.
|
||||
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Modern software engineering frequently begins with a familiar question:
|
||||
|
||||
> **"Which framework should we use?"**
|
||||
|
||||
NX9 begins with a different question:
|
||||
|
||||
> **"Do we need one at all?"**
|
||||
|
||||
This distinction is fundamental.
|
||||
|
||||
NX9 is not opposed to frameworks.
|
||||
|
||||
Frameworks such as React, Angular, Laravel, Spring Boot, Django, and Next.js have solved genuine engineering problems at enormous scale.
|
||||
|
||||
React solved Facebook's UI challenges.
|
||||
|
||||
Angular addressed Google's enterprise applications.
|
||||
|
||||
Laravel transformed PHP productivity.
|
||||
|
||||
Those are significant engineering achievements.
|
||||
|
||||
The question NX9 asks is simply:
|
||||
|
||||
> **Does our project have those same problems?**
|
||||
|
||||
Many self-hosted services do not.
|
||||
|
||||
A documentation website.
|
||||
|
||||
A URL shortener.
|
||||
|
||||
An authentication server.
|
||||
|
||||
A digital timestamping service.
|
||||
|
||||
A lightweight dashboard.
|
||||
|
||||
These applications often require reliability, simplicity, maintainability, and operational transparency far more than they require extensive framework ecosystems.
|
||||
|
||||
NX9 therefore adopts a different philosophy.
|
||||
|
||||
---
|
||||
|
||||
# The NX9 Philosophy
|
||||
|
||||
Every NX9 project follows a common set of engineering principles.
|
||||
|
||||
* Privacy First
|
||||
* Self-Hosted First
|
||||
* Linux Native
|
||||
* Rust Native
|
||||
* Single Binary Applications
|
||||
* Explicit Routing
|
||||
* Minimal Dependencies
|
||||
* Open Source (FOSS)
|
||||
* No Vendor Lock-In
|
||||
* Operational Simplicity
|
||||
|
||||
Rather than beginning with a framework and removing features, NX9 begins with the application itself and adds only the software required to solve the problem.
|
||||
|
||||
Nothing more.
|
||||
|
||||
Nothing less.
|
||||
|
||||
---
|
||||
|
||||
# Complexity Is Not Free
|
||||
|
||||
Every dependency introduces responsibility.
|
||||
|
||||
Someone must eventually:
|
||||
|
||||
* install it;
|
||||
* configure it;
|
||||
* update it;
|
||||
* monitor it;
|
||||
* patch it;
|
||||
* audit it;
|
||||
* understand it.
|
||||
|
||||
Modern web applications frequently include:
|
||||
|
||||
* thousands of npm packages;
|
||||
* hundreds of indirect dependencies;
|
||||
* build systems;
|
||||
* transpilers;
|
||||
* runtime environments;
|
||||
* middleware layers;
|
||||
* plugins;
|
||||
* framework conventions.
|
||||
|
||||
Each component may be valuable.
|
||||
|
||||
Collectively, they also increase operational complexity and expand the software that must be maintained throughout the application's lifetime.
|
||||
|
||||
NX9 therefore asks a much simpler engineering question:
|
||||
|
||||
> **Can this problem be solved with significantly less software?**
|
||||
|
||||
If the answer is yes, simplicity becomes the preferred engineering decision.
|
||||
|
||||
---
|
||||
|
||||
# Production Snapshot
|
||||
|
||||
This study is based entirely on production access logs collected after **nx9.in** became publicly accessible.
|
||||
|
||||
This was **not**:
|
||||
|
||||
* a penetration test;
|
||||
* a laboratory simulation;
|
||||
* synthetic benchmark traffic.
|
||||
|
||||
It was ordinary Internet traffic.
|
||||
|
||||
Within a short period of public exposure:
|
||||
|
||||
* automated vulnerability scanners began probing the server;
|
||||
* legitimate browsers accessed the published website;
|
||||
* Twitter/X generated preview cards;
|
||||
* search crawlers indexed the content;
|
||||
* additional independent scanners continued probing throughout the observation period.
|
||||
|
||||
---
|
||||
|
||||
# Observed Traffic
|
||||
|
||||
During the observation period:
|
||||
|
||||
| Response | Count | Percentage |
|
||||
| ---------------- | ------: | ---------: |
|
||||
| 404 Not Found | **331** | **91.4%** |
|
||||
| 304 Not Modified | 20 | 5.5% |
|
||||
| 200 OK | 11 | 3.1% |
|
||||
|
||||
The most striking observation is that **over 91% of incoming requests were not attempts to use the application.**
|
||||
|
||||
They were attempts to discover software that was never deployed.
|
||||
|
||||
---
|
||||
|
||||
# What Were the Bots Looking For?
|
||||
|
||||
Representative examples include:
|
||||
|
||||
```text
|
||||
/.env
|
||||
/vendor/.env
|
||||
/wp-admin/
|
||||
/wp-content/
|
||||
/wp-includes/
|
||||
/phpinfo.php
|
||||
/admin.php
|
||||
/public/css.php
|
||||
/f35.php
|
||||
/222.php
|
||||
/chosen.php
|
||||
/vercel.json
|
||||
/vite.config.ts
|
||||
/vendors~main.bundle.js
|
||||
/vue/
|
||||
/v1/admin/
|
||||
```
|
||||
|
||||
These requests reveal remarkably consistent assumptions.
|
||||
|
||||
| Requested Resource | What the Scanner Expected |
|
||||
| ------------------------ | --------------------------- |
|
||||
| `.env` | Laravel / PHP configuration |
|
||||
| `vendor/.env` | Composer project |
|
||||
| `wp-admin` | WordPress |
|
||||
| `wp-content` | WordPress plugins |
|
||||
| `phpinfo.php` | PHP runtime |
|
||||
| `admin.php` | PHP administration panel |
|
||||
| `f35.php` | PHP web shell |
|
||||
| `public/css.php` | Vulnerable PHP application |
|
||||
| `vite.config.ts` | Vite project |
|
||||
| `vendors~main.bundle.js` | Webpack / React build |
|
||||
| `vercel.json` | Vercel deployment |
|
||||
| `vue/.env` | Vue application |
|
||||
|
||||
The scanners were not attempting to identify NX9.
|
||||
|
||||
They were attempting to identify technologies commonly deployed across today's Internet.
|
||||
|
||||
---
|
||||
|
||||
# What Actually Happened?
|
||||
|
||||
Every vulnerability probe received essentially the same response.
|
||||
|
||||
```text
|
||||
404 Not Found
|
||||
```
|
||||
|
||||
Not because NX9 blocked the request.
|
||||
|
||||
Not because a Web Application Firewall intercepted it.
|
||||
|
||||
Not because an intrusion detection system analyzed it.
|
||||
|
||||
The requested resources simply did not exist.
|
||||
|
||||
This distinction is critical.
|
||||
|
||||
There is a significant engineering difference between software successfully defending itself and software that was never deployed in the first place.
|
||||
|
||||
---
|
||||
|
||||
# Explicit Routing
|
||||
|
||||
NX9 applications expose only routes intentionally defined by the developer.
|
||||
|
||||
Conceptually:
|
||||
|
||||
```text
|
||||
/
|
||||
├── /
|
||||
├── /projects
|
||||
├── /about
|
||||
├── /contact
|
||||
└── 404
|
||||
```
|
||||
|
||||
There is:
|
||||
|
||||
* no automatic controller discovery;
|
||||
* no runtime file resolution;
|
||||
* no directory-based routing;
|
||||
* no framework-generated endpoints.
|
||||
|
||||
If a route was never implemented, it simply cannot be reached.
|
||||
|
||||
Unknown requests terminate immediately at the fallback handler.
|
||||
|
||||
---
|
||||
|
||||
# Security Begins Before Deployment
|
||||
|
||||
Security is often discussed in terms of:
|
||||
|
||||
* firewalls;
|
||||
* intrusion detection systems;
|
||||
* endpoint protection;
|
||||
* monitoring platforms.
|
||||
|
||||
Those remain valuable.
|
||||
|
||||
However, architecture itself is also a security decision.
|
||||
|
||||
The NX9 deployment contained:
|
||||
|
||||
* no PHP interpreter;
|
||||
* no WordPress;
|
||||
* no Laravel;
|
||||
* no Composer vendor directory;
|
||||
* no Node.js runtime;
|
||||
* no exposed `.env`;
|
||||
* no framework-generated administration interface;
|
||||
* no debug endpoints.
|
||||
|
||||
Those components were never installed.
|
||||
|
||||
Consequently, they never became part of the deployment's attack surface.
|
||||
|
||||
This is not **security through obscurity**.
|
||||
|
||||
It is **security through intentional software selection**.
|
||||
|
||||
---
|
||||
|
||||
# A Smaller Stack
|
||||
|
||||
Many modern web deployments resemble:
|
||||
|
||||
```text
|
||||
Internet
|
||||
│
|
||||
▼
|
||||
Reverse Proxy
|
||||
│
|
||||
▼
|
||||
Runtime
|
||||
│
|
||||
▼
|
||||
Framework
|
||||
│
|
||||
▼
|
||||
Middleware
|
||||
│
|
||||
▼
|
||||
Plugins
|
||||
│
|
||||
▼
|
||||
Packages
|
||||
│
|
||||
▼
|
||||
Application
|
||||
```
|
||||
|
||||
NX9 deliberately reduces the deployment:
|
||||
|
||||
```text
|
||||
Internet
|
||||
│
|
||||
▼
|
||||
Nginx
|
||||
│
|
||||
▼
|
||||
Rust Binary
|
||||
│
|
||||
▼
|
||||
Explicit Route Table
|
||||
│
|
||||
▼
|
||||
Application Logic
|
||||
```
|
||||
|
||||
The objective is not minimalism for its own sake.
|
||||
|
||||
The objective is engineering proportional to the problem being solved.
|
||||
|
||||
---
|
||||
|
||||
# Frameworks Are Not the Enemy
|
||||
|
||||
This case study should not be interpreted as criticism of frameworks.
|
||||
|
||||
Frameworks solve difficult engineering problems.
|
||||
|
||||
Many projects genuinely require them.
|
||||
|
||||
NX9 simply argues that every dependency should justify its existence.
|
||||
|
||||
Engineering is not about choosing the most fashionable technology.
|
||||
|
||||
It is about choosing the most appropriate technology.
|
||||
|
||||
Sometimes that means a sophisticated framework.
|
||||
|
||||
Sometimes that means a single Rust binary.
|
||||
|
||||
---
|
||||
|
||||
# Legitimate Traffic Continued Normally
|
||||
|
||||
An equally important observation is what **did** work.
|
||||
|
||||
Legitimate clients successfully accessed the application throughout the observation period.
|
||||
|
||||
This included:
|
||||
|
||||
* desktop browsers;
|
||||
* Android browsers;
|
||||
* Twitter/X preview generation;
|
||||
* search engine crawlers;
|
||||
* browser cache validation (`304 Not Modified`).
|
||||
|
||||
The minimal deployment remained fully functional for intended users while exposing no unnecessary application surface.
|
||||
|
||||
---
|
||||
|
||||
# Non-Goals
|
||||
|
||||
This article does **not** claim:
|
||||
|
||||
* that Rust is immune to vulnerabilities;
|
||||
* that frameworks are insecure;
|
||||
* that 404 responses alone provide security;
|
||||
* that NX9 cannot contain bugs.
|
||||
|
||||
Instead, it demonstrates a much simpler engineering principle:
|
||||
|
||||
> **Software that is never deployed cannot become part of your deployment's attack surface.**
|
||||
|
||||
---
|
||||
|
||||
# Lessons Learned
|
||||
|
||||
The production logs reveal a surprisingly simple truth.
|
||||
|
||||
The overwhelming majority of unsolicited Internet traffic was not exploring the application itself.
|
||||
|
||||
It was exploring assumptions.
|
||||
|
||||
The scanners assumed:
|
||||
|
||||
* PHP;
|
||||
* WordPress;
|
||||
* Laravel;
|
||||
* Vue;
|
||||
* Node.js;
|
||||
* Composer;
|
||||
* Vite;
|
||||
* Vercel;
|
||||
* common administration panels.
|
||||
|
||||
NX9 deliberately deployed none of them.
|
||||
|
||||
The result was not that sophisticated defensive software defeated the attacks.
|
||||
|
||||
The result was that the attacks found nothing matching their expectations.
|
||||
|
||||
---
|
||||
|
||||
# Conclusion
|
||||
|
||||
Every NX9 project begins with the same engineering question:
|
||||
|
||||
> **What is the smallest amount of software required to solve this problem well?**
|
||||
|
||||
Sometimes that answer includes a framework.
|
||||
|
||||
Often it does not.
|
||||
|
||||
This case study demonstrates that software minimalism is not merely an aesthetic preference.
|
||||
|
||||
It is an architectural decision with practical operational consequences.
|
||||
|
||||
During the observed period, more than **91%** of incoming requests were attempts to identify technologies that simply were not present.
|
||||
|
||||
That outcome was not accidental.
|
||||
|
||||
It was the direct consequence of choosing a smaller, simpler, explicitly designed software stack.
|
||||
|
||||
**Build only what you need.**
|
||||
|
||||
**Deploy only what you trust.**
|
||||
|
||||
**Maintain only what you own.**
|
||||
|
||||
Because every component you choose **not** to deploy is one less component to configure, patch, monitor, audit—and one less component available to be targeted.
|
||||
|
||||
**That is the NX9 philosophy.**
|
||||
@@ -0,0 +1,52 @@
|
||||
# License
|
||||
|
||||
Copyright © 2026 Sunil Thakare
|
||||
|
||||
This project is licensed under **either** of the following licenses, at your option:
|
||||
|
||||
* Apache License, Version 2.0
|
||||
* MIT License
|
||||
|
||||
You may choose either license for your use of this software.
|
||||
|
||||
---
|
||||
|
||||
## Apache License 2.0
|
||||
|
||||
Copyright © 2026 Sunil Thakare
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this software except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
> https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an **"AS IS" BASIS**,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
---
|
||||
|
||||
## MIT License
|
||||
|
||||
Copyright © 2026 Sunil Thakare
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED **"AS IS"**, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,122 @@
|
||||
# NX9 Philosophy: Engineering Beyond Frameworks
|
||||
|
||||
**A real-world case study in software minimalism, explicit routing, and reduced attack surface**
|
||||
|
||||
> "The best way to reduce complexity is not to manage more software—it is to deploy less software."
|
||||
|
||||
## Introduction
|
||||
|
||||
Modern software engineering often begins with a familiar question:
|
||||
|
||||
> "Which framework should we use?"
|
||||
|
||||
NX9 begins with a different question:
|
||||
|
||||
> "Do we need one at all?"
|
||||
|
||||
This is not an argument against frameworks. Frameworks like React, Angular, Laravel, Spring Boot, and Next.js have solved incredibly hard problems and transformed development.
|
||||
|
||||
But they solved *specific* problems.
|
||||
|
||||
A personal website, a self-hosted utility, an authentication service, a URL shortener, or an infrastructure component rarely requires thousands of JavaScript packages, multiple runtimes, extensive middleware chains, complex build pipelines, and enormous dependency trees simply to deliver its intended functionality.
|
||||
|
||||
For many projects, complexity becomes the default — not the requirement.
|
||||
|
||||
NX9 deliberately chooses another path.
|
||||
|
||||
## Production Snapshot
|
||||
|
||||
The observations presented in this article come directly from the production logs of **nx9.in** after its first public deployment.
|
||||
|
||||
They are **not** the result of a penetration test, laboratory simulation, or synthetic benchmark.
|
||||
|
||||
During the observation period:
|
||||
|
||||
- Multiple independent vulnerability scanners began probing the server shortly after public exposure.
|
||||
- Automated requests targeted common framework artifacts, PHP files, WordPress installations, Laravel configuration, Vue projects, Docker deployments, and build-system outputs.
|
||||
- Every vulnerability probe resulted in **404 Not Found**.
|
||||
- Legitimate visitors — including desktop browsers, Android devices, Twitter/X crawlers, search crawlers, and internal users — continued to access the published resources normally.
|
||||
|
||||
These observations provide a useful real-world case study of the NX9 engineering philosophy.
|
||||
|
||||
## Engineering Beyond Frameworks
|
||||
|
||||
NX9 is founded on a simple engineering principle:
|
||||
|
||||
> Deploy only the software necessary to solve the problem.
|
||||
> Nothing more.
|
||||
> Nothing less.
|
||||
|
||||
Every project within the NX9 ecosystem follows the same philosophy:
|
||||
|
||||
- Privacy First
|
||||
- Self-Hosted First
|
||||
- Linux Native
|
||||
- Rust Native
|
||||
- Single Binary Applications
|
||||
- Explicit Routing
|
||||
- Minimal Dependencies
|
||||
- Open Source (FOSS)
|
||||
- No Vendor Lock-In
|
||||
- Operational Simplicity
|
||||
|
||||
Frameworks are not avoided because they are "bad."
|
||||
|
||||
They are avoided when they solve problems the application simply does not have.
|
||||
|
||||
Every dependency should justify its existence.
|
||||
Every abstraction should earn its maintenance cost.
|
||||
Every additional component should provide value greater than the complexity it introduces.
|
||||
|
||||
## Complexity Has a Cost
|
||||
|
||||
Modern applications are often assembled from enormous dependency trees.
|
||||
|
||||
A simple "Hello World" project may involve:
|
||||
|
||||
- thousands of npm packages
|
||||
- hundreds of transitive dependencies
|
||||
- multiple build tools
|
||||
- package managers
|
||||
- runtime environments
|
||||
- framework-specific tooling
|
||||
- automated code generation
|
||||
|
||||
Each component is individually useful.
|
||||
Collectively, they increase operational responsibility.
|
||||
|
||||
Every additional dependency must eventually be:
|
||||
|
||||
- installed
|
||||
- configured
|
||||
- updated
|
||||
- audited
|
||||
- monitored
|
||||
- patched
|
||||
- understood
|
||||
|
||||
NX9 asks a simple engineering question:
|
||||
|
||||
> Can this problem be solved with significantly less software?
|
||||
|
||||
If the answer is yes, simplicity becomes the preferred design.
|
||||
|
||||
## Real-World Validation
|
||||
|
||||
Shortly after **nx9.in** became publicly accessible, automated scanners began probing the server.
|
||||
|
||||
The requests were not random. They were highly characteristic of Internet-wide reconnaissance targeting common deployment technologies.
|
||||
|
||||
Representative examples included:
|
||||
|
||||
```text
|
||||
/.env
|
||||
/vendor/.env
|
||||
/wp-admin/
|
||||
/wp-content/
|
||||
/phpinfo.php
|
||||
/vercel.json
|
||||
/vite.config.ts
|
||||
/vendors~main.bundle.js
|
||||
/vue/
|
||||
/v1/admin/
|
||||
@@ -0,0 +1,66 @@
|
||||
# NX9
|
||||
|
||||
**Next Generation 9** — A philosophy-driven ecosystem of self-hosted, privacy-first software.
|
||||
|
||||
Every project is built around one core idea:
|
||||
|
||||
> **Infrastructure should belong to its operator — not to a cloud provider, subscription service, or vendor.**
|
||||
|
||||
### Philosophy
|
||||
|
||||
NX9 is not a framework or a platform. It is a collection of independent, single-binary Rust applications designed for:
|
||||
|
||||
- Operator ownership
|
||||
- Privacy by default
|
||||
- Self-hosting first
|
||||
- Simplicity over complexity
|
||||
- Long-term maintainability
|
||||
- Zero telemetry or vendor lock-in
|
||||
|
||||
We deliberately choose minimal dependencies, explicit routing, SQLite-first storage, and Linux-native design. The goal is software that is easy to understand, deploy, operate, and trust — even years from now.
|
||||
|
||||
### Core Projects
|
||||
|
||||
- **[nx9-url-shortener](https://codeberg.org/thakares/nx9-url-shortener)**
|
||||
Multi-user URL shortener with analytics, QR codes, password protection, expiration, and tenant isolation.
|
||||
|
||||
- **[nx9-auth](https://codeberg.org/thakares/nx9-auth)**
|
||||
Lightweight identity and access management service with sessions, PATs, RBAC, and audit logging.
|
||||
|
||||
- **[nx9-dns-server](https://codeberg.org/thakares/nx9-dns-server)**
|
||||
Authoritative DNS server with DNSSEC support. Lightweight and designed for self-hosted use.
|
||||
|
||||
- **[nx9-chronoseal-rs](https://codeberg.org/thakares/nx9-chronoseal-rs)**
|
||||
Privacy-first browser attestation framework for anti-bot and anti-AI scraping protection.
|
||||
|
||||
### Documentation
|
||||
|
||||
- [Philosophy → Engineering Beyond Frameworks](https://nx9.in/case-study.html)
|
||||
- [Architecture Overview](ARCHITECTURE.md)
|
||||
- [Case Study: How Simplicity Defended Against Real Attacks](https://nx9.in/case-study.html)
|
||||
- [Roadmap](ROADMAP.md)
|
||||
|
||||
### Website
|
||||
|
||||
The full website source is available in the [`www/`](www/) directory.
|
||||
|
||||
### Values
|
||||
|
||||
- Privacy by design
|
||||
- Single binary deployments
|
||||
- Explicit routing
|
||||
- Operator sovereignty
|
||||
- Open Source (permissive licenses)
|
||||
- No telemetry. No vendor lock-in.
|
||||
|
||||
### Get Involved
|
||||
|
||||
- Star or fork the projects you find useful
|
||||
- Open issues or discussions for feedback
|
||||
- All projects are independent but share the same architectural principles
|
||||
|
||||
---
|
||||
|
||||
**NX9** — Software people can own, understand, and control.
|
||||
|
||||
Built by [Sunil Thakare](https://codeberg.org/thakares).
|
||||
@@ -0,0 +1,440 @@
|
||||
# NX9 Roadmap
|
||||
|
||||
> **Engineering Beyond Frameworks**
|
||||
>
|
||||
> *Building a complete ecosystem of self-hosted, privacy-first, single-binary applications.*
|
||||
|
||||
---
|
||||
|
||||
# Vision
|
||||
|
||||
NX9 is not a single application.
|
||||
|
||||
It is an ecosystem of independent, interoperable, self-hosted tools designed around a common engineering philosophy:
|
||||
|
||||
* Build only what is necessary.
|
||||
* Avoid unnecessary frameworks.
|
||||
* Minimize dependencies.
|
||||
* Keep deployments simple.
|
||||
* Respect user privacy.
|
||||
* Eliminate vendor lock-in.
|
||||
* Remain fully open source.
|
||||
|
||||
Every project should be deployable in minutes, understandable by a single engineer, and maintainable for years—not months.
|
||||
|
||||
---
|
||||
|
||||
# Core Principles
|
||||
|
||||
Every NX9 project follows the same architectural principles.
|
||||
|
||||
## Privacy First
|
||||
|
||||
No telemetry.
|
||||
|
||||
No tracking.
|
||||
|
||||
No analytics.
|
||||
|
||||
Your data belongs to you.
|
||||
|
||||
---
|
||||
|
||||
## Self-Hosted First
|
||||
|
||||
Cloud deployment is optional.
|
||||
|
||||
Self-hosting is the default.
|
||||
|
||||
Users should own their infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## Linux Native
|
||||
|
||||
Linux is the primary deployment platform.
|
||||
|
||||
Applications should feel like first-class Linux software.
|
||||
|
||||
---
|
||||
|
||||
## Rust Native
|
||||
|
||||
Rust provides:
|
||||
|
||||
* predictable performance
|
||||
* memory safety
|
||||
* modern tooling
|
||||
* excellent concurrency
|
||||
* minimal runtime requirements
|
||||
|
||||
---
|
||||
|
||||
## Single Binary Applications
|
||||
|
||||
Whenever practical:
|
||||
|
||||
* one executable
|
||||
* one configuration directory
|
||||
* one service
|
||||
* one deployment
|
||||
|
||||
No dependency on heavyweight runtime ecosystems.
|
||||
|
||||
---
|
||||
|
||||
## Explicit Over Implicit
|
||||
|
||||
Nothing should happen "by convention."
|
||||
|
||||
Routes.
|
||||
|
||||
Configuration.
|
||||
|
||||
Permissions.
|
||||
|
||||
Features.
|
||||
|
||||
Everything should be explicit.
|
||||
|
||||
---
|
||||
|
||||
## Minimal Dependencies
|
||||
|
||||
Dependencies are engineering decisions—not conveniences.
|
||||
|
||||
Every dependency:
|
||||
|
||||
* increases maintenance
|
||||
* expands attack surface
|
||||
* introduces supply-chain risk
|
||||
|
||||
If a problem can be solved internally with reasonable effort, that may be preferable to importing another dependency.
|
||||
|
||||
---
|
||||
|
||||
## Operational Simplicity
|
||||
|
||||
Deployment should be boring.
|
||||
|
||||
Installation should be boring.
|
||||
|
||||
Upgrades should be boring.
|
||||
|
||||
Reliability is more valuable than cleverness.
|
||||
|
||||
---
|
||||
|
||||
# Current Projects
|
||||
|
||||
## BZOD
|
||||
|
||||
**Status:** Stable
|
||||
|
||||
Privacy-first URL shortener.
|
||||
|
||||
Features include:
|
||||
|
||||
* custom aliases
|
||||
* QR codes
|
||||
* expiration
|
||||
* password protection
|
||||
* analytics
|
||||
* audit logs
|
||||
* REST API
|
||||
* SQLite
|
||||
* PostgreSQL
|
||||
* Docker
|
||||
* single-binary deployment
|
||||
|
||||
---
|
||||
|
||||
## nx9-auth
|
||||
|
||||
**Status:** Active Development
|
||||
|
||||
Authentication platform designed for self-hosted applications.
|
||||
|
||||
Goals include:
|
||||
|
||||
* OAuth2
|
||||
* OpenID Connect
|
||||
* JWT
|
||||
* session management
|
||||
* user management
|
||||
* API authentication
|
||||
* SSO for NX9 ecosystem
|
||||
|
||||
---
|
||||
|
||||
## ChronoSeal
|
||||
|
||||
**Status:** Planned
|
||||
|
||||
Digital timestamping platform.
|
||||
|
||||
Goals:
|
||||
|
||||
* trusted timestamping
|
||||
* immutable records
|
||||
* hash verification
|
||||
* document integrity
|
||||
* long-term verification
|
||||
|
||||
---
|
||||
|
||||
# Planned Ecosystem
|
||||
|
||||
The long-term objective is a cohesive ecosystem where every application shares the same design philosophy and integrates naturally with the others.
|
||||
|
||||
Potential projects include:
|
||||
|
||||
## File Sharing
|
||||
|
||||
Simple.
|
||||
|
||||
Fast.
|
||||
|
||||
Self-hosted.
|
||||
|
||||
No unnecessary complexity.
|
||||
|
||||
---
|
||||
|
||||
## Password Manager
|
||||
|
||||
Encrypted.
|
||||
|
||||
Offline-first.
|
||||
|
||||
Self-hostable.
|
||||
|
||||
---
|
||||
|
||||
## Notification Service
|
||||
|
||||
Email.
|
||||
|
||||
Webhooks.
|
||||
|
||||
Push.
|
||||
|
||||
Simple API.
|
||||
|
||||
---
|
||||
|
||||
## Monitoring Dashboard
|
||||
|
||||
Infrastructure monitoring.
|
||||
|
||||
System health.
|
||||
|
||||
Container health.
|
||||
|
||||
Notifications.
|
||||
|
||||
---
|
||||
|
||||
## Documentation Platform
|
||||
|
||||
Markdown-first.
|
||||
|
||||
Fast.
|
||||
|
||||
Searchable.
|
||||
|
||||
Single binary.
|
||||
|
||||
---
|
||||
|
||||
## Workflow Automation
|
||||
|
||||
Simple automation engine for self-hosted infrastructure.
|
||||
|
||||
Designed for practical administration rather than enterprise complexity.
|
||||
|
||||
---
|
||||
|
||||
# Technical Direction
|
||||
|
||||
## Frontend
|
||||
|
||||
Preference for:
|
||||
|
||||
* HTML5
|
||||
* CSS3
|
||||
* Vanilla JavaScript
|
||||
|
||||
JavaScript frameworks should only be introduced when they solve demonstrable engineering problems.
|
||||
|
||||
---
|
||||
|
||||
## Backend
|
||||
|
||||
Primary language:
|
||||
|
||||
* Rust
|
||||
|
||||
Preferred characteristics:
|
||||
|
||||
* async
|
||||
* efficient
|
||||
* predictable
|
||||
* memory safe
|
||||
|
||||
---
|
||||
|
||||
## Database
|
||||
|
||||
Primary:
|
||||
|
||||
* SQLite
|
||||
|
||||
Optional:
|
||||
|
||||
* PostgreSQL
|
||||
|
||||
Applications should not require a database server unless the workload justifies it.
|
||||
|
||||
---
|
||||
|
||||
## APIs
|
||||
|
||||
REST-first.
|
||||
|
||||
JSON.
|
||||
|
||||
Well documented.
|
||||
|
||||
Versioned.
|
||||
|
||||
Simple.
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
Supported environments:
|
||||
|
||||
* Linux
|
||||
* Docker
|
||||
* Podman
|
||||
|
||||
Future consideration:
|
||||
|
||||
* FreeBSD
|
||||
|
||||
---
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
Recommended:
|
||||
|
||||
* Nginx
|
||||
|
||||
Applications should work behind any standards-compliant reverse proxy.
|
||||
|
||||
---
|
||||
|
||||
# Security Philosophy
|
||||
|
||||
Security begins with architecture.
|
||||
|
||||
NX9 emphasizes:
|
||||
|
||||
* explicit routing
|
||||
* reduced attack surface
|
||||
* minimal dependencies
|
||||
* least privilege
|
||||
* secure defaults
|
||||
* modern cryptography
|
||||
* reproducible builds
|
||||
|
||||
Security features should emerge naturally from good engineering—not from accumulating layers of defensive software.
|
||||
|
||||
---
|
||||
|
||||
# Non-Goals
|
||||
|
||||
NX9 does **not** aim to:
|
||||
|
||||
* replace every web framework;
|
||||
* eliminate JavaScript;
|
||||
* compete with enterprise platforms;
|
||||
* build monolithic "all-in-one" systems;
|
||||
* chase technology trends;
|
||||
* optimize for resume-driven development.
|
||||
|
||||
The objective is thoughtful engineering, not ideological minimalism.
|
||||
|
||||
---
|
||||
|
||||
# Design Philosophy
|
||||
|
||||
Every new feature should answer three questions:
|
||||
|
||||
1. Does it solve a real problem?
|
||||
2. Can it be implemented simply?
|
||||
3. Does it increase long-term maintenance disproportionately?
|
||||
|
||||
If the answer to the third question is **yes**, the feature should be reconsidered.
|
||||
|
||||
---
|
||||
|
||||
# Success Criteria
|
||||
|
||||
A successful NX9 application should be:
|
||||
|
||||
* understandable by reading the source;
|
||||
* deployable within minutes;
|
||||
* maintainable by a small team—or even a single developer;
|
||||
* performant without extraordinary hardware;
|
||||
* secure through simplicity;
|
||||
* pleasant to operate.
|
||||
|
||||
---
|
||||
|
||||
# Community Principles
|
||||
|
||||
NX9 welcomes contributions that align with its philosophy.
|
||||
|
||||
Preferred contributions include:
|
||||
|
||||
* bug fixes
|
||||
* documentation
|
||||
* accessibility improvements
|
||||
* performance optimizations
|
||||
* security improvements
|
||||
* interoperability
|
||||
* code simplification
|
||||
|
||||
Contributions that significantly increase complexity without corresponding long-term value may not align with the project's direction.
|
||||
|
||||
---
|
||||
|
||||
# Looking Forward
|
||||
|
||||
The goal of NX9 is not to build the largest software ecosystem.
|
||||
|
||||
It is to build one of the most coherent.
|
||||
|
||||
Every project should feel familiar.
|
||||
|
||||
Every deployment should feel predictable.
|
||||
|
||||
Every application should respect the user's ownership of their data and infrastructure.
|
||||
|
||||
The roadmap will continue to evolve as new ideas emerge, but one principle will remain unchanged:
|
||||
|
||||
> **Choose the simplest architecture capable of solving the problem well.**
|
||||
|
||||
Because software should empower its users—not burden them with unnecessary complexity.
|
||||
|
||||
---
|
||||
|
||||
**NX9**
|
||||
|
||||
*Engineering Beyond Frameworks.*
|
||||
*Build only what you need.*
|
||||
*Deploy only what you trust.*
|
||||
*Maintain only what you own.*
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 896 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
||||
@@ -0,0 +1,47 @@
|
||||
name: nx9-www
|
||||
services:
|
||||
nx9-www:
|
||||
cpu_shares: 90
|
||||
command: []
|
||||
container_name: nx9-www
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 31940M
|
||||
hostname: nx9-www-www
|
||||
image: nginx:alpine
|
||||
labels:
|
||||
icon: https://github.com/thakares/nx9-www-rs/raw/main/logo/nx9-www.svg
|
||||
ports:
|
||||
- mode: ingress
|
||||
target: 80
|
||||
published: "8484"
|
||||
protocol: tcp
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /DATA/AppData/nx9-www
|
||||
target: /usr/share/nginx/html
|
||||
read_only: true
|
||||
bind:
|
||||
create_host_path: true
|
||||
devices: []
|
||||
cap_add: []
|
||||
environment: []
|
||||
networks:
|
||||
- default
|
||||
privileged: false
|
||||
networks:
|
||||
default:
|
||||
name: nx9-www_default
|
||||
x-casaos:
|
||||
author: self
|
||||
category: self
|
||||
hostname: ""
|
||||
icon: https://github.com/thakares/nx9-www-rs/raw/main/logo/nx9-www.svg
|
||||
index: /
|
||||
is_uncontrolled: false
|
||||
port_map: "8484"
|
||||
scheme: http
|
||||
title:
|
||||
custom: nx9-www
|
||||
|
After Width: | Height: | Size: 697 B |
|
After Width: | Height: | Size: 850 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="150 200 280 196" width="100%" height="100%">
|
||||
<g fill="#ffffff">
|
||||
<rect x="150" y="200" width="280" height="48" rx="24"/>
|
||||
<rect x="150" y="260" width="280" height="48" rx="24"/>
|
||||
<rect x="150" y="320" width="280" height="48" rx="24"/>
|
||||
<rect x="278" y="368" width="24" height="18"/>
|
||||
<rect x="235" y="386" width="110" height="12"/>
|
||||
<rect x="150" y="388" width="73" height="8"/>
|
||||
<rect x="357" y="388" width="73" height="8"/>
|
||||
</g>
|
||||
<g fill="#020617"> <!-- Very dark slate to match theme backgrounds -->
|
||||
<circle cx="400" cy="224" r="8"/>
|
||||
<circle cx="400" cy="284" r="8"/>
|
||||
<circle cx="400" cy="344" r="8"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,39 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="145 195 810 215" width="100%" height="100%">
|
||||
<!-- Background -->
|
||||
|
||||
<g fill="#ffffff">
|
||||
<!-- Server Rack Blades -->
|
||||
<!-- Top -->
|
||||
<rect x="150" y="200" width="280" height="48" rx="24"/>
|
||||
<!-- Middle -->
|
||||
<rect x="150" y="260" width="280" height="48" rx="24"/>
|
||||
<!-- Bottom -->
|
||||
<rect x="150" y="320" width="280" height="48" rx="24"/>
|
||||
|
||||
<!-- Stem -->
|
||||
<rect x="278" y="368" width="24" height="18"/>
|
||||
|
||||
<!-- Base plate -->
|
||||
<rect x="235" y="386" width="110" height="12"/>
|
||||
|
||||
<!-- Network Lines -->
|
||||
<!-- Left -->
|
||||
<rect x="150" y="388" width="73" height="8"/>
|
||||
<!-- Right -->
|
||||
<rect x="357" y="388" width="73" height="8"/>
|
||||
</g>
|
||||
|
||||
<!-- LEDs (Cutouts) -->
|
||||
<g fill="#000000">
|
||||
<circle cx="400" cy="224" r="8"/>
|
||||
<circle cx="400" cy="284" r="8"/>
|
||||
<circle cx="400" cy="344" r="8"/>
|
||||
</g>
|
||||
|
||||
<!-- Main Logo Text -->
|
||||
<text x="470" y="368" font-family="'Montserrat', 'Arial Black', 'Impact', sans-serif" font-size="235" font-weight="900" fill="#ffffff" letter-spacing="-4">NX9</text>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<text x="485" y="400" font-family="'Montserrat', 'Segoe UI', 'Helvetica Neue', sans-serif" font-size="26" font-weight="700" fill="#ffffff" letter-spacing="2">OWN YOUR INFRASTRUCTURE.</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "App",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |