This commit is contained in:
Raven Scott 2024-09-18 19:15:41 -04:00
parent 9ff7d0bc8c
commit 2d0d653e83

View File

@ -129,6 +129,188 @@ cmd(`node /home/scripts/gen_multi.js ${sshUserID} ubuntu ${interaction.user.id}`
The `gen_multi.js` script handles all aspects of container deployment, including setting up the operating system, assigning network resources, and provisioning SSH access. The operating system is selected based on user input, and various distributions are supported, such as Ubuntu, Debian, Arch, Alpine, and more.
### Understanding the gen_multi.js script
This script is a powerful tool designed to automate the deployment and management of Docker containers. It leverages several key Node.js modules and libraries to streamline the process, making it ideal for handling various Linux distributions and container orchestration. Lets walk through how it works, with code examples to illustrate each step.
#### Key Libraries and Dependencies
At the heart of the script are some critical Node.js libraries. The `unirest` library is used to make HTTP requests, while `Dockerode` provides a powerful Docker client for managing containers. The script also uses `cmd-promise` to execute shell commands in a promise-based manner. For logging, `log-to-file` is used, and it integrates with Discord via `discord.js` for sending logs or status updates.
Additionally, the script incorporates MySQL (`mysql2`) to interact with a database, allowing the script to store and retrieve user-specific data, such as user identifiers and resource configurations.
#### Handling Randomness Network Selection
The script uses a helper function `randomIntFromInterval` to generate random integers within a specified range. This randomness plays a critical role in assigning ports (`rand1`, `rand2`) and selecting a random network from a predefined list (`networkNames`). These random values help in dynamically configuring Docker containers and ensuring that no two containers accidentally use the same ports or networks.
```javascript
function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
let networkNames = ["ct1", "ct2", "ct3", "ct4", ...]; // A predefined list of networks
let randNetwork = networkNames[Math.floor(Math.random() * networkNames.length)];
```
#### MySQL Connection Setup
A MySQL connection is established using the `mysql2` library. The credentials (host, user, password, and database) are predefined. The database interaction allows the script to query user data, such as retrieving user-specific configuration values needed for container setup.
```javascript
connection.query(
"SELECT * FROM users WHERE uid = '" + myArgs[4] + "'",
function (err, results) {
if (results.length === 0) {
console.log("User does not exist");
} else {
console.log(results);
}
}
);
```
#### Detecting IP and Caching Network Configurations
The script runs a shell command via `cmd-promise` to detect the IP address associated with a randomly chosen network. Once the IP is detected, a network cache file is created and written to using `jsonfile`, saving the random network configuration for later use.
```javascript
cmd(`sh /home/scripts/detectIP.sh ` + randNetwork).then(out => {
let IPAddress = out.stdout.replace("\n", "");
const jsonfile = require('jsonfile');
const file = '/home/cache/netcache/' + myArgs[4] + ".network";
const obj = { id: randNetwork };
jsonfile.writeFile(file, obj).then(() => {
console.log('Network Cache Write complete');
});
});
```
#### Operating System Selection
The script supports multiple Linux distributions, such as Ubuntu, Debian, CentOS, and more. Depending on the command-line arguments passed, the script selects the appropriate operating system for the Docker container. Each OS is associated with specific resource settings (e.g., memory, CPUs) and restart policies, all configurable based on user input.
For example, if Ubuntu is chosen, the script sets the Docker image to `ssh:ubuntu`, assigns memory and CPU limits, and specifies that the container should always restart (`--restart always`). Other OS options, like Alpine or CentOS, follow similar logic but with different configurations.
```javascript
if (opperatingSystem === "ubuntu") {
osChosen = "ssh:ubuntu";
restartVar = "--restart always";
memoryVar = "--memory=1024m --memory-swap=1080m";
cpusVar = "--cpus=2";
specialPorts = "";
} else if (opperatingSystem === "alpine") {
osChosen = "ssh:alpine";
restartVar = "--restart always";
memoryVar = "--memory=1024m --memory-swap=1080m";
cpusVar = "--cpus=2";
specialPorts = "";
}
```
#### Container Creation and Docker Run
Once the OS is selected and configured, the script attempts to run a Docker container using `dockerode`. It constructs a `docker run` command with a set of options, including DNS configuration, memory limits, CPU limits, and custom network settings. The script also checks if the user has a trial key; if so, it uses `--rm` to automatically remove the container after use.
```javascript
cmd(`docker run --dns 1.2.3.4 --ulimit nofile=10000:50000 --mount type=bind,source=/etc/hosts,target=/etc/hosts,readonly -e PATH=/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nodejs/bin:/usr/local/go/bin:/root/.cargo/bin:/root/.go/bin --ip ${IPAddress} -td ` + freeStorage + " " + specialStartup + ' --network=' + randNetwork + " -e CONTAINER_NAME=" + myArgs[4] + " " + trialVar + " " + memoryVar + " " + cpusVar + " " + restartVar + ' --hostname ' + myArgs[4] + ' --name ' + myArgs[4] + " " + osChosen).then(out => {
console.log("Container Created Successfully");
})
.catch(err => {
console.log('Error:', err);
});
```
### Key Elements of the Command
#### `docker run`
This is the core Docker command that starts a new container. It is followed by various options and configurations that tailor how the container will be run.
#### `--dns 1.2.3.4`
This option sets the DNS server for the container to `1.2.3.4`. This can be used to force the container to use a specific DNS server instead of the system default.
#### `--ulimit nofile=10000:50000`
The `ulimit` option is used to control the number of open file descriptors allowed in the container. In this case, the limit is set to a soft limit of 10,000 and a hard limit of 50,000. This is particularly useful when dealing with containers that require a large number of file handles, such as servers with heavy network or file I/O activity.
#### `--mount type=bind,source=/etc/hosts,target=/etc/hosts,readonly`
This bind mount command maps the host machines `/etc/hosts` file into the containers `/etc/hosts` path as a read-only file. It allows the container to access the same host-to-IP mappings as the host system, ensuring consistency in DNS lookups within the container.
#### `-e PATH=/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nodejs/bin:/usr/local/go/bin:/root/.cargo/bin:/root/.go/bin`
The `-e` flag sets environment variables inside the container. In this case, it modifies the `PATH` environment variable to include several common directories where executable files are located, including Node.js, Go, and system binaries.
#### `--ip ${IPAddress}`
This option sets a specific IP address for the container. The variable `${IPAddress}` is dynamically set in the script, likely determined earlier based on network or configuration.
#### `-td`
These two flags are combined:
- `-t` allocates a pseudo-TTY (terminal), which is useful for interactive applications.
- `-d` runs the container in detached mode, meaning it runs in the background.
#### `${freeStorage} ${specialStartup}`
These variables are used to dynamically inject additional options for storage and startup configurations. They are passed as part of the Docker run command:
- `freeStorage` might define storage-related options such as volume mounting or storage limits.
- `specialStartup` likely contains commands or environment variables that are executed or passed when the container starts.
#### `--network=${randNetwork}`
This specifies the Docker network to which the container will be connected. The variable `randNetwork` contains the name of the network, which is chosen randomly in the script from a predefined list of network names.
#### `-e CONTAINER_NAME=${myArgs[4]}`
This sets an environment variable `CONTAINER_NAME` inside the container, with the value coming from the command-line argument `myArgs[4]`. This is useful for tracking or logging the containers name during execution.
#### `${trialVar} ${memoryVar} ${cpusVar} ${restartVar}`
These variables are used to define additional container settings:
- `trialVar`: Determines if the container is part of a trial, potentially adding `--rm` to automatically remove the container when it stops.
- `memoryVar`: Sets memory limits for the container, such as `--memory=1024m` to limit the container to 1024 MB of RAM.
- `cpusVar`: Specifies CPU limits, for example, `--cpus=2` to restrict the container to 2 CPU cores.
- `restartVar`: Adds a restart policy to the container, such as `--restart always` to ensure the container restarts automatically if it crashes or is stopped.
#### `--hostname ${myArgs[4]} --name ${myArgs[4]}`
These options set the hostname and name of the container, both based on the value of `myArgs[4]`. The hostname is the internal network name of the container, while the name is how the container will be referenced in Docker.
#### `${osChosen}`
Finally, the `${osChosen}` variable specifies which Docker image to use when creating the container. This variable is dynamically set based on the chosen operating system earlier in the script.
#### Handling Edge Cases and Custom Roles
The script has specific conditions for handling users with custom roles. For example, if a user has certain roles, they are allocated more resources (CPUs, memory). Conversely, for trial users, the resources are limited.
Additionally, there are special conditions for certain user IDs, where specific storage or CPU configurations are assigned, providing flexibility based on user requirements.
```javascript
if (myArgs[4] === "SSH42113405732790") {
cpusVar = "--cpus=8";
memoryVar = "--memory=8192m";
freeStorage = "--storage-opt size=50G";
}
```
#### Logging and Finalizing the Order
Throughout the process, the script logs important events, such as when a new order is received or when a container is successfully deployed. These logs are written both to the console and to a log file (`orders_generated.log`). This ensures that administrators can monitor the deployment process and track potential issues.
```javascript
log('------New Order Received--------', 'orders_generated.log');
log('Container Created Successfully', 'orders_generated.log');
```
Once the container is deployed, the script updates the users network ID in the MySQL database, ensuring that the network configuration is properly tracked. Finally, it logs the successful completion of the order and exits.
```javascript
async function updateNetworkID(netID, sshSurfID) {
connection.query(
"UPDATE users SET netid='" + netID + "' WHERE uid='" + sshSurfID + "'",
function (err, results) {
console.log(results);
}
);
}
```
---
This script is a highly customizable and automated solution for managing Docker containers, tailored to dynamically handle various Linux distributions and custom resource allocations based on user input. The use of random network and port assignment ensures that each container is unique, while the integration with MySQL and external APIs adds a layer of user management and user-specific configurations. By combining these powerful tools, the script efficiently handles container orchestration, making it a robust solution for system administrators.
### Container Configuration
The system dynamically configures the container's resources based on the user's selection and available system resources. It adjusts memory, CPU allocation, and storage space to ensure the container runs optimally. Here's a simplified configuration process: